// Copyright (c) 2021, 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: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/ast.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/generated/resolver.dart';

class CommentReferenceResolver {
  final TypeProviderImpl _typeProvider;

  final ResolverVisitor _resolver;

  /// Helper for resolving properties on types.
  final TypePropertyResolver _typePropertyResolver;

  CommentReferenceResolver(this._typeProvider, this._resolver)
      : _typePropertyResolver = _resolver.typePropertyResolver;

  /// Resolves [commentReference].
  void resolve(CommentReference commentReference) {
    var expression = commentReference.expression;
    if (expression is SimpleIdentifierImpl) {
      _resolveSimpleIdentifierReference(expression,
          hasNewKeyword: commentReference.newKeyword != null);
    } else if (expression is PrefixedIdentifierImpl) {
      _resolvePrefixedIdentifierReference(expression,
          hasNewKeyword: commentReference.newKeyword != null);
    } else if (expression is PropertyAccessImpl) {
      _resolvePropertyAccessReference(expression,
          hasNewKeyword: commentReference.newKeyword != null);
    }
  }

  void _resolvePrefixedIdentifierReference(
    PrefixedIdentifierImpl expression, {
    required bool hasNewKeyword,
  }) {
    var prefix = expression.prefix;
    var prefixElement = _resolveSimpleIdentifier(prefix);
    prefix.staticElement = prefixElement;

    if (prefixElement == null) {
      return;
    }

    var name = expression.identifier;

    if (prefixElement is PrefixElement) {
      var prefixScope = prefixElement.scope;
      var lookupResult = prefixScope.lookup(name.name);
      var element = lookupResult.getter ?? lookupResult.setter;
      element = _resolver.toLegacyElement(element);
      name.staticElement = element;
      return;
    }

    if (!hasNewKeyword) {
      if (prefixElement is ClassElement) {
        name.staticElement = prefixElement.getMethod(name.name) ??
            prefixElement.getGetter(name.name) ??
            prefixElement.getSetter(name.name) ??
            prefixElement.getNamedConstructor(name.name);
      } else if (prefixElement is ExtensionElement) {
        name.staticElement = prefixElement.getMethod(name.name) ??
            prefixElement.getGetter(name.name) ??
            prefixElement.getSetter(name.name);
      } else {
        // TODO(brianwilkerson) Report this error.
      }
    } else if (prefixElement is ClassElement) {
      var constructor = prefixElement.getNamedConstructor(name.name);
      if (constructor == null) {
        // TODO(brianwilkerson) Report this error.
      } else {
        name.staticElement = constructor;
      }
    } else {
      // TODO(brianwilkerson) Report this error.
    }
  }

  void _resolvePropertyAccessReference(
    PropertyAccessImpl expression, {
    required bool hasNewKeyword,
  }) {
    var target = expression.target;
    if (target is! PrefixedIdentifierImpl) {
      // A PropertyAccess with a target more complex than a
      // [PrefixedIdentifier] is not a valid comment reference.
      return;
    }

    var prefix = target.prefix;
    var prefixElement = _resolveSimpleIdentifier(prefix);
    prefix.staticElement = prefixElement;

    if (prefixElement is! PrefixElement) {
      // The only valid prefixElement is a PrefixElement; otherwise, this is
      // not a comment reference.
      return;
    }

    var name = target.identifier;
    var prefixScope = prefixElement.scope;
    var lookupResult = prefixScope.lookup(name.name);
    var element = lookupResult.getter ?? lookupResult.setter;
    element = _resolver.toLegacyElement(element);
    name.staticElement = element;

    var propertyName = expression.propertyName;
    if (element is ClassElement) {
      propertyName.staticElement = element.getMethod(propertyName.name) ??
          element.getGetter(propertyName.name) ??
          element.getSetter(propertyName.name) ??
          element.getNamedConstructor(propertyName.name);
    } else if (element is ExtensionElement) {
      propertyName.staticElement = element.getMethod(propertyName.name) ??
          element.getGetter(propertyName.name) ??
          element.getSetter(propertyName.name);
    }
  }

  /// Resolves the given simple [identifier] if possible.
  ///
  /// Returns the resolved element, or `null` if the identifier could not be
  /// resolved. This does not record the results of the resolution.
  Element? _resolveSimpleIdentifier(SimpleIdentifierImpl identifier) {
    var lookupResult = identifier.scopeLookupResult!;

    var element = _resolver.toLegacyElement(lookupResult.getter) ??
        _resolver.toLegacyElement(lookupResult.setter);

    if (element == null) {
      InterfaceType enclosingType;
      var enclosingClass = _resolver.enclosingClass;
      if (enclosingClass != null) {
        enclosingType = enclosingClass.thisType;
      } else {
        var enclosingExtension = _resolver.enclosingExtension;
        if (enclosingExtension == null) {
          return null;
        }
        var extendedType = enclosingExtension.extendedType
            .resolveToBound(_typeProvider.objectType);
        if (extendedType is InterfaceType) {
          enclosingType = extendedType;
        } else if (extendedType is FunctionType) {
          enclosingType = _typeProvider.functionType;
        } else {
          return null;
        }
      }
      var result = _typePropertyResolver.resolve(
        receiver: null,
        receiverType: enclosingType,
        name: identifier.name,
        propertyErrorEntity: identifier,
        nameErrorEntity: identifier,
      );
      element = result.getter ?? result.setter;
    }
    return element;
  }

  void _resolveSimpleIdentifierReference(
    SimpleIdentifierImpl expression, {
    required bool hasNewKeyword,
  }) {
    var element = _resolveSimpleIdentifier(expression);
    if (element == null) {
      return;
    }
    expression.staticElement = element;
    if (hasNewKeyword) {
      if (element is ClassElement) {
        var constructor = element.unnamedConstructor;
        if (constructor == null) {
          // TODO(brianwilkerson) Report this error.
        } else {
          expression.staticElement = constructor;
        }
      } else {
        // TODO(brianwilkerson) Report this error.
      }
    }
  }
}
