// Copyright (c) 2014, 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/protocol/protocol_generated.dart'
    show HoverInformation;
import 'package:analysis_server/src/computer/computer_documentation.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.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/dart/element/extensions.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:path/path.dart' as path;

/// Information about a library to display in a hover.
typedef _LibraryInfo = ({String? libraryName, String? libraryPath})?;
typedef _OffsetLength = ({int offset, int length});

/// A computer for the hover at the specified offset of a Dart
/// [CompilationUnit].
class DartUnitHoverComputer {
  final CompilationUnit _unit;
  final int _offset;
  final DartDocumentationComputer _documentationComputer;

  new(DartdocDirectiveInfo dartdocInfo, this._unit, this._offset)
    : _documentationComputer = DartDocumentationComputer(dartdocInfo);

  /// Returns the computed hover, maybe `null`.
  HoverInformation? compute() {
    var node = _unit.nodeCovering(offset: _offset);
    if (node == null) {
      return null;
    }

    var locationEntity = _locationEntity(node, _offset);
    node = _targetNode(node);
    if (node == null || locationEntity == null) {
      return null;
    }

    if (node is CompilationUnitMember ||
        node is CatchClauseParameter ||
        node is EnumConstantDeclaration ||
        node is Expression ||
        node is FormalParameter ||
        node is MethodDeclaration ||
        node is NamedArgument ||
        node is NamedType ||
        node is ConstructorDeclaration ||
        node is DeclaredIdentifier ||
        node is RecordLiteralNamedField ||
        node is VariableDeclaration ||
        node is VariablePattern ||
        node is PatternFieldName ||
        node is PrimaryConstructorBody ||
        node is PrimaryConstructorDeclaration ||
        node is PrimaryConstructorName ||
        node is DartPattern ||
        (node is LibraryDirective && node.name == null) ||
        (node is SimpleIdentifier && node.parent is ImportDirective) ||
        node is ImportPrefixReference) {
      var range = _hoverRange(node, locationEntity);
      var hover = HoverInformation(range.offset, range.length);
      // element
      var element = ElementLocator.locate(node);
      if (element != null && element.isWildcardVariable) {
        return null;
      }
      if (element case var elementReference?) {
        // short code that illustrates the element meaning.
        hover.elementDescription = _elementDisplayString(
          node,
          elementReference,
        );
        hover.elementKind = elementReference.kind.displayName;
        hover.isDeprecated = elementReference.isDeprecatedWithKind('use');
        // not local element
        if (node.parent
            case GenericFunctionType(
              parent: Declaration(
                    declaredFragment: Fragment(element: var declared),
                  ) ||
                  FormalParameter(
                    declaredFragment: Fragment(element: var declared),
                  ) ||
                  GenericTypeAlias(
                    declaredFragment: Fragment(element: var declared),
                  ),
            )
            when elementReference.enclosingElement
                is GenericFunctionTypeElement) {
          var list = hover.containingExecutableDescriptions ??= [];
          list.add(declared.displayName);
          elementReference = declared;
        }
        var enclosingElement = elementReference.enclosingElement;
        while (true) {
          if (enclosingElement case ExecutableElement(
            enclosingElement: var enclosing,
            :var displayName,
          )) {
            if (enclosingElement case ConstructorElement(name: 'new')) {
              displayName = 'new';
            } else if (enclosingElement case LocalFunctionElement(
              firstFragment: Fragment(:var enclosingFragment?),
            )) {
              enclosing = enclosingFragment.element;
            }
            enclosingElement = enclosing;
            var list = hover.containingExecutableDescriptions ??= [];
            list.add(displayName);
          } else {
            break;
          }
        }
        // containing instance
        hover.containingClassDescription = _containingInstance(
          elementReference,
        );
        if (elementReference.enclosingElement is! ExecutableElement ||
            (hover.containingExecutableDescriptions?.isNotEmpty ?? false)) {
          // containing library
          var libraryInfo = _libraryInfo(elementReference);
          hover.containingLibraryName = libraryInfo?.libraryName;
          hover.containingLibraryPath = libraryInfo?.libraryPath;
        }
        // documentation
        hover.dartdoc = _documentationComputer.compute(elementReference)?.full;
      }
      // parameter
      hover.parameter = _parameterDisplayString(node);
      // types
      hover.staticType = _typeDisplayString(node, element);
      // done
      return hover;
    }
    // not an expression
    return null;
  }

  /// Gets the name of the containing class of [element].
  String? _containingInstance(Element element) {
    var containingClass = element.thisOrAncestorOfType<InterfaceElement>();
    return containingClass != null && containingClass != element
        ? containingClass.displayName
        : null;
  }

  /// Gets the display string for [element].
  ///
  /// This is usually `element.getDisplayString()` but may contain additional
  /// information to disambiguate things like constructors from types (and
  /// whether they are const).
  String? _elementDisplayString(AstNode node, Element? element) {
    var displayString = element?.displayString(
      multiline: true,
      includePositionalParameterNames: true,
    );

    if (displayString != null) {
      if (element is TypeParameterElement) {
        displayString = '<$displayString>';
      } else if (node is InstanceCreationExpression && node.keyword == null) {
        var prefix = node.isConst ? '(const) ' : '(new) ';
        displayString = prefix + displayString;
      } else if (node is DotShorthandConstructorInvocation) {
        var prefix = node.isConst ? '(const) ' : '(new) ';
        displayString = prefix + displayString;
      }
    }

    return displayString;
  }

  /// Computes the range this hover applies to.
  ///
  /// This is usually the range of [entity] but may be adjusted for entities
  /// like constructor names.
  _OffsetLength _hoverRange(AstNode node, SyntacticEntity entity) {
    // For constructors, the location should cover the type name and
    // constructor name (for both calls and declarations).
    if (node is InstanceCreationExpression) {
      return (
        offset: node.constructorName.offset,
        length: node.constructorName.length,
      );
    } else if (node is DotShorthandConstructorInvocation) {
      return (offset: node.offset, length: node.length);
    } else if (node is ConstructorDeclaration) {
      var offset =
          node.typeName?.offset ??
          node.newKeyword?.offset ??
          node.factoryKeyword!.offset;
      var end =
          node.name?.end ??
          node.typeName?.end ??
          node.newKeyword?.end ??
          node.factoryKeyword!.end;
      var length = end - offset;
      return (offset: offset, length: length);
    } else if (node is PrimaryConstructorDeclaration) {
      if (node.constructorName != null) {
        return (offset: entity.offset, length: entity.length);
      }
      var offset = node.typeName.offset;
      var end = node.typeName.end;
      var length = end - offset;
      return (offset: offset, length: length);
    } else {
      return (offset: entity.offset, length: entity.length);
    }
  }

  /// Returns information about the library that contains [element].
  _LibraryInfo _libraryInfo(Element element) {
    var library = element.library;
    if (library == null) {
      return null;
    }

    var definingSource = library.firstFragment.source;
    var uri = definingSource.uri;
    var analysisSession = _unit.declaredFragment?.element.session;

    String? libraryName, libraryPath;
    // for 'file:' URIs, use the path after the package root
    if (uri.isScheme('file') && analysisSession != null) {
      var pathContext = analysisSession.resourceProvider.pathContext;
      var libraryFilePath = pathContext.fromUri(uri);
      var contextRoot = analysisSession.analysisContext.contextRoot;
      var workspace = contextRoot.workspace;

      // Prefer using the root of the package that contains this library, since
      // the context root could now be a Pub Workspace. If we don't find one,
      // fall back to the context root.
      var package = workspace.packages.packageForPath(libraryFilePath);
      var packageRootDir = package?.rootFolder.path ?? contextRoot.root.path;

      var relativePath = pathContext.relative(
        libraryFilePath,
        from: packageRootDir,
      );
      if (pathContext.style == path.Style.windows) {
        var pathList = pathContext.split(relativePath);
        libraryName = pathList.join('/');
      } else {
        libraryName = relativePath;
      }
    } else {
      libraryName = uri.toString();
    }
    libraryPath = definingSource.fullName;

    return (libraryName: libraryName, libraryPath: libraryPath);
  }

  /// Returns the [SyntacticEntity] that should be used as the range for this
  /// hover.
  ///
  /// Returns `null` if there is no valid entity for this hover.
  SyntacticEntity? _locationEntity(AstNode node, int offset) {
    return switch (node) {
      BinaryExpression() => node.operator,
      ConditionalExpression()
          when offset >= node.question.offset && offset <= node.question.end =>
        node.question,
      ConditionalExpression()
          when offset >= node.colon.offset && offset <= node.colon.end =>
        node.colon,
      AssignmentExpression() => node.operator,
      PrefixExpression() => node.operator,
      PostfixExpression() => node.operator,
      CatchClauseParameter() => node.name,
      ClassDeclaration() => node.namePart.typeName,
      ConstructorDeclaration() =>
        node.name ?? node.typeName ?? node.newKeyword ?? node.factoryKeyword,
      DeclaredIdentifier() => node.name,
      EnumConstantDeclaration() => node.name,
      EnumDeclaration() => node.namePart.typeName,
      Expression() => node,
      ExtensionDeclaration() => node.name,
      ExtensionTypeDeclaration() => node.namePart.typeName,
      FormalParameter() => node.name,
      FunctionDeclaration() => node.name,
      ImportPrefixReference() => node.name,
      LibraryDirective() => node.libraryKeyword,
      MethodDeclaration() => node.name,
      NamedArgument() => node.name,
      MixinDeclaration() => node.name,
      NameWithTypeParameters() => node.typeName,
      NamedType() => node.name,
      PatternFieldName() => node.name,
      PrimaryConstructorBody() =>
        node.declaration?.constructorName ?? node.declaration?.typeName,
      PrimaryConstructorDeclaration() => node.constructorName ?? node.typeName,
      PrimaryConstructorName() => node.name,
      RecordLiteralNamedField() => node.name,
      TypeAlias() => node.name,
      VariableDeclaration() => node.name,
      VariablePattern() => node.name,
      WildcardPattern() => node.name,
      _ => null,
    };
  }

  /// Gets the display string for the type of the parameter.
  ///
  /// Returns `null` if the node doesn't correspond to a parameter.
  String? _parameterDisplayString(AstNode node) {
    FormalParameterElement? parameter;
    if (node is Argument) {
      parameter = node.correspondingParameter;
    }
    return switch (parameter?.enclosingElement) {
      // Expressions passed as arguments to setters and binary expressions
      // will have parameters here but we don't want them to show as such in
      // hovers because information about those functions are already available
      // by hovering over the function name or the operator.
      SetterElement() => null,
      MethodElement method when method.isOperator => null,
      _ => _elementDisplayString(node, parameter),
    };
  }

  /// Adjusts the target node for constructors.
  AstNode? _targetNode(AstNode node) {
    var parent = node.parent;
    var parent2 = parent?.parent;
    if (node is ClassNamePart) {
      return parent;
    } else if (parent is NamedType &&
        parent2 is ConstructorName &&
        parent2.parent is InstanceCreationExpression) {
      return parent2.parent;
    } else if (parent is ConstructorName &&
        parent2 is InstanceCreationExpression) {
      return parent2;
    } else if (node is SimpleIdentifier &&
        parent is ConstructorDeclaration &&
        parent.name != null) {
      return parent;
    } else if (node is SimpleIdentifier &&
        parent is DotShorthandConstructorInvocation) {
      return parent;
    }
    return node;
  }

  /// Returns information about the static type of [node].
  String? _typeDisplayString(AstNode node, Element? element) {
    var parent = node.parent;
    DartType? staticType;
    if (node is NamedArgument) {
      staticType = node.correspondingParameter?.type;
    } else if (node is Expression &&
        (element == null ||
            element is VariableElement ||
            element is GetterElement ||
            element is SetterElement)) {
      staticType = _getTypeOfDeclarationOrReference(node);
    } else if (element is VariableElement) {
      staticType = element.type;
    } else if (parent is MethodInvocation && parent.methodName == node) {
      staticType = parent.staticInvokeType;
      if (staticType != null && staticType is DynamicType) {
        staticType = null;
      }
    } else if (parent is PrefixedIdentifier && parent.identifier == node) {
      staticType = parent.identifier.staticType;
      if (staticType != null && staticType is DynamicType) {
        staticType = null;
      }
    } else if (parent is DotShorthandInvocation && parent.memberName == node) {
      staticType = parent.staticInvokeType;
      if (staticType != null && staticType is DynamicType) {
        staticType = null;
      }
    } else if (node is PatternFieldName && parent is PatternField) {
      staticType = parent.pattern.matchedValueType;
    } else if (node is DartPattern) {
      staticType = node.matchedValueType;
    }
    return staticType?.getDisplayString();
  }

  static DartType? _getTypeOfDeclarationOrReference(Expression node) {
    if (node is SimpleIdentifier) {
      var element = node.element;
      if (element is VariableElement) {
        if (node.inDeclarationContext()) {
          return element.type;
        }
      }
      var parent = node.parent;
      var parent2 = parent?.parent;

      if (parent is AssignmentExpression && parent.leftHandSide == node) {
        // Direct setter reference
        return parent.writeType;
      } else if (parent2 is AssignmentExpression &&
          parent2.leftHandSide == parent) {
        if (parent is PrefixedIdentifier && parent.identifier == node) {
          // Prefixed setter (`myInstance.foo =`)
          return parent2.writeType;
        } else if (parent is PropertyAccess && parent.propertyName == node) {
          // Expression prefix (`A<int>().foo =`)
          return parent2.writeType;
        }
      }
    }
    return node.staticType;
  }
}
