// 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/src/computer/computer_documentation.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/element_locator.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';

/// A computer for the signature at the specified offset of a Dart
/// [CompilationUnit].
class DartUnitSignatureComputer {
  final AstNode? _node;
  final int _offset;
  final DocumentationPreference documentationPreference;
  final DartDocumentationComputer _documentationComputer;

  DartUnitSignatureComputer(
    DartdocDirectiveInfo dartdocInfo,
    CompilationUnit unit,
    this._offset, {
    this.documentationPreference = DocumentationPreference.full,
  }) : _documentationComputer = DartDocumentationComputer(dartdocInfo),
       _node = unit.nodeCovering(offset: _offset);

  bool get offsetIsValid => _node != null;

  /// Returns the computed signature information, maybe `null`.
  SignatureInformation? compute() {
    var argumentAndList = _findArgumentAndList();
    if (argumentAndList == null) {
      return null;
    }
    var (argumentList, argument) = argumentAndList;
    String? name;
    Element? element;
    List<FormalParameterElement>? parameters;
    var parent = argumentList.parent;
    if (parent is MethodInvocation) {
      name = parent.methodName.name;
      element = ElementLocator.locate2(parent);
      parameters =
          element is FunctionTypedElement ? element.formalParameters : null;
    } else if (parent is InstanceCreationExpression) {
      name = parent.constructorName.type.qualifiedName;
      var constructorName = parent.constructorName.name;
      if (constructorName != null) {
        name += '.${constructorName.name}';
      }
      element = ElementLocator.locate2(parent);
      parameters =
          element is FunctionTypedElement ? element.formalParameters : null;
    } else if (parent case FunctionExpressionInvocation(
      function: Identifier function,
    )) {
      name = function.name;

      if (function.staticType case FunctionType functionType) {
        // Standard function expression.
        element = function.element;
        parameters = functionType.formalParameters;
      } else if (parent.element case ExecutableElement executableElement) {
        // Callable class instance (where we'll look at the `call` method).
        element = executableElement;
        parameters = executableElement.formalParameters;
      }
    }

    if (name == null || element == null || parameters == null) {
      return null;
    }

    // Try to compute the active parameter so the IDE can highlight it.
    int? activeParameterIndex;
    if (argument case Expression(:var correspondingParameter?)) {
      // If we know the active parameter, use its index.
      activeParameterIndex = parameters.indexOf(correspondingParameter);
    } else if (argument is! NamedExpression) {
      // If we're not a named expression, then we can count how many positional
      // parameters there are before us, and then find the index of the same
      // index positional parameter.
      var positionalArgsToSkip =
          argumentList.arguments
              .where((argument) => argument is! NamedExpression)
              .takeWhile((argument) => argument.end < _offset)
              .length;
      for (var i = 0; i < parameters.length; i++) {
        if (parameters[i].isPositional) {
          // This is the first positional parameter after our skips, so this is
          // the active parameter.
          if (positionalArgsToSkip == 0) {
            activeParameterIndex = i;
            break;
          }
          positionalArgsToSkip--;
        }
      }
    }

    var dartdoc = _documentationComputer.computePreferred(
      element,
      documentationPreference,
    );

    return SignatureInformation(
      name: name,
      parameters: parameters,
      argumentList: argumentList,
      activeParameterIndex: activeParameterIndex,
      dartdoc: dartdoc,
    );
  }

  /// Return the closest argument list surrounding the [_node] and the node for
  /// the active argument (if there is one).
  (ArgumentList, AstNode?)? _findArgumentAndList() {
    var node = _node;
    while (node != null) {
      // Certain nodes don't make sense to search above for an argument list
      // (for example when inside a function expression).
      if (node is FunctionExpression) {
        return null;
      }

      if (node is ArgumentList) {
        return (node, null);
      }
      if (node.parent case ArgumentList list) {
        return (list, node);
      }

      node = node.parent;
    }
    return null;
  }
}

/// Information about a function signature.
class SignatureInformation {
  /// The name of the function/method.
  final String name;

  /// The parameters for the function/method.
  final List<FormalParameterElement> parameters;

  /// The current argument list at the invocation site.
  final ArgumentList argumentList;

  /// Documentation for the function/method.
  final String? dartdoc;

  /// The index in [parameters] for the parameter that matches where the offset
  /// was in the invocation list.
  ///
  /// This is only supplied when it can be computed. Positional arguments past
  /// the number of positional parameters or named arguments with no matching
  /// name will not be returned.
  final int? activeParameterIndex;

  SignatureInformation({
    required this.name,
    required this.parameters,
    required this.argumentList,
    required this.activeParameterIndex,
    required this.dartdoc,
  });

  AnalysisGetSignatureResult toLegacyProtocol() {
    return AnalysisGetSignatureResult(
      name,
      parameters.map(_convertParam).toList(),
      dartdoc: dartdoc,
    );
  }

  ParameterInfo _convertParam(FormalParameterElement param) {
    return ParameterInfo(
      param.isOptionalNamed
          ? ParameterKind.OPTIONAL_NAMED
          : param.isOptionalPositional
          ? ParameterKind.OPTIONAL_POSITIONAL
          : param.isRequiredNamed
          ? ParameterKind.REQUIRED_NAMED
          : ParameterKind.REQUIRED_POSITIONAL,
      param.displayName,
      param.type.getDisplayString(),
      defaultValue: param.defaultValueCode,
    );
  }
}
