// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol_generated.dart'
    hide AnalysisGetNavigationParams;
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
import 'package:collection/collection.dart';

class DefinitionHandler extends MessageHandler<TextDocumentPositionParams,
        Either2<List<Location>, List<LocationLink>>>
    with LspPluginRequestHandlerMixin {
  DefinitionHandler(LspAnalysisServer server) : super(server);
  @override
  Method get handlesMessage => Method.textDocument_definition;

  @override
  LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
      TextDocumentPositionParams.jsonHandler;

  Future<List<AnalysisNavigationParams>> getPluginResults(
    String path,
    int offset,
  ) async {
    // LSP requests must be converted to DAS-protocol requests for compatibility
    // with plugins.
    final requestParams = plugin.AnalysisGetNavigationParams(path, offset, 0);
    final responses = await requestFromPlugins(path, requestParams);

    return responses
        .map((response) =>
            plugin.AnalysisGetNavigationResult.fromResponse(response))
        .map((result) => AnalysisNavigationParams(
            path, result.regions, result.targets, result.files))
        .toList();
  }

  Future<AnalysisNavigationParams> getServerResult(
      bool supportsLocationLink, String path, int offset) async {
    final collector = NavigationCollectorImpl();

    final result = await server.getResolvedUnit(path);
    final unit = result?.unit;
    if (unit != null) {
      computeDartNavigation(
          server.resourceProvider, collector, unit, offset, 0);
      if (supportsLocationLink) {
        _updateTargetsWithCodeLocations(collector);
      }
      collector.createRegions();
    }

    return AnalysisNavigationParams(
        path, collector.regions, collector.targets, collector.files);
  }

  @override
  Future<ErrorOr<Either2<List<Location>, List<LocationLink>>>> handle(
      TextDocumentPositionParams params, CancellationToken token) async {
    final clientCapabilities = server.clientCapabilities;
    if (clientCapabilities == null) {
      // This should not happen unless a client misbehaves.
      return error(ErrorCodes.ServerNotInitialized,
          'Requests not before server is initilized');
    }

    final supportsLocationLink = clientCapabilities.definitionLocationLink;

    final pos = params.position;
    final path = pathOfDoc(params.textDocument);

    return path.mapResult((path) async {
      final lineInfo = server.getLineInfo(path);
      // If there is no lineInfo, the request cannot be translated from LSP line/col
      // to server offset/length.
      if (lineInfo == null) {
        return success(
          Either2<List<Location>, List<LocationLink>>.t1(const []),
        );
      }

      final offset = toOffset(lineInfo, pos);

      return offset.mapResult((offset) async {
        final allResults = [
          await getServerResult(supportsLocationLink, path, offset),
          ...await getPluginResults(path, offset),
        ];

        final merger = ResultMerger();
        final mergedResults = merger.mergeNavigation(allResults);
        final mergedTargets = mergedResults?.targets ?? [];

        if (mergedResults == null) {
          return success(
            Either2<List<Location>, List<LocationLink>>.t1(const []),
          );
        }

        // Convert and filter the results using the correct type of Location class
        // depending on the client capabilities.
        if (supportsLocationLink) {
          final convertedResults = convert(
            mergedTargets,
            (NavigationTarget target) =>
                _toLocationLink(mergedResults, lineInfo, target),
          ).whereNotNull().toList();

          final results = _filterResults(
            convertedResults,
            params.textDocument.uri,
            pos.line,
            (LocationLink element) => element.targetUri,
            (LocationLink element) => element.targetSelectionRange,
          );

          return success(
            Either2<List<Location>, List<LocationLink>>.t2(results),
          );
        } else {
          final convertedResults = convert(
            mergedTargets,
            (NavigationTarget target) => _toLocation(mergedResults, target),
          ).whereNotNull().toList();

          final results = _filterResults(
            convertedResults,
            params.textDocument.uri,
            pos.line,
            (Location element) => element.uri,
            (Location element) => element.range,
          );

          return success(
            Either2<List<Location>, List<LocationLink>>.t1(results),
          );
        }
      });
    });
  }

  /// Helper that selects the correct results (filtering out at the same
  /// line/location) generically, handling either type of Location class.
  List<T> _filterResults<T>(
    List<T> results,
    String sourceUri,
    int sourceLineNumber,
    String Function(T) uriSelector,
    Range Function(T) rangeSelector,
  ) {
    // If we fetch navigation on a keyword like `var`, the results will include
    // both the definition and also the variable name. This will cause the editor
    // to show the user both options unnecessarily (the variable name is always
    // adjacent to the var keyword, so providing navigation to it is not useful).
    // To prevent this, filter the list to only those on different lines (or
    // different files).
    final otherResults = results
        .where((element) =>
            uriSelector(element) != sourceUri ||
            rangeSelector(element).start.line != sourceLineNumber)
        .toList();

    return otherResults.isNotEmpty ? otherResults : results;
  }

  /// Get the location of the code (excluding leading doc comments) for this element.
  protocol.Location? _getCodeLocation(Element element) {
    var codeElement = element;
    // For synthetic getters created for fields, we need to access the associated
    // variable to get the codeOffset/codeLength.
    if (codeElement.isSynthetic && codeElement is PropertyAccessorElementImpl) {
      final variable = codeElement.variable;
      if (variable is ElementImpl) {
        codeElement = variable as ElementImpl;
      }
    }

    // Read the main codeOffset from the element. This may include doc comments
    // but will give the correct end position.
    int? codeOffset, codeLength;
    if (codeElement is ElementImpl) {
      codeOffset = codeElement.codeOffset;
      codeLength = codeElement.codeLength;
    }

    if (codeOffset == null || codeLength == null) {
      return null;
    }

    // Read the declaration so we can get the offset after the doc comments.
    // TODO(dantup): Skip this for parts (getParsedLibrary will throw), but find
    // a better solution.
    final declaration = _parsedDeclaration(codeElement);
    var node = declaration?.node;
    if (node is VariableDeclaration) {
      node = node.parent;
    }
    if (node is AnnotatedNode) {
      var offsetAfterDocs = node.firstTokenAfterCommentAndMetadata.offset;

      // Reduce the length by the difference between the end of docs and the start.
      codeLength -= offsetAfterDocs - codeOffset;
      codeOffset = offsetAfterDocs;
    }

    return AnalyzerConverter()
        .locationFromElement(element, offset: codeOffset, length: codeLength);
  }

  Location? _toLocation(
      AnalysisNavigationParams mergedResults, NavigationTarget target) {
    final targetFilePath = mergedResults.files[target.fileIndex];
    final targetLineInfo = server.getLineInfo(targetFilePath);
    return targetLineInfo != null
        ? navigationTargetToLocation(targetFilePath, target, targetLineInfo)
        : null;
  }

  LocationLink? _toLocationLink(AnalysisNavigationParams mergedResults,
      LineInfo sourceLineInfo, NavigationTarget target) {
    final region = mergedResults.regions.first;
    final targetFilePath = mergedResults.files[target.fileIndex];
    final targetLineInfo = server.getLineInfo(targetFilePath);

    return targetLineInfo != null
        ? navigationTargetToLocationLink(
            region, sourceLineInfo, targetFilePath, target, targetLineInfo)
        : null;
  }

  void _updateTargetsWithCodeLocations(NavigationCollectorImpl collector) {
    for (var targetToUpdate in collector.targetsToUpdate) {
      var codeLocation = _getCodeLocation(targetToUpdate.element);
      if (codeLocation != null) {
        targetToUpdate.target
          ..codeOffset = codeLocation.offset
          ..codeLength = codeLocation.length;
      }
    }
  }

  static ElementDeclarationResult? _parsedDeclaration(Element element) {
    var session = element.session;
    if (session == null) {
      return null;
    }

    var libraryPath = element.library?.source.fullName;
    if (libraryPath == null) {
      return null;
    }

    var parsedLibrary = session.getParsedLibrary(libraryPath);
    if (parsedLibrary is! ParsedLibraryResult) {
      return null;
    }

    return parsedLibrary.getElementDeclaration(element);
  }
}
