// Copyright (c) 2020, 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/error/listener.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:collection/collection.dart';

class DeprecatedMemberUseVerifier {
  final WorkspacePackage? _workspacePackage;
  final ErrorReporter _errorReporter;

  /// We push a new value every time when we enter into a scope which
  /// can be marked as deprecated - a class, a method, fields (multiple).
  final List<bool> _inDeprecatedMemberStack = [false];

  DeprecatedMemberUseVerifier(this._workspacePackage, this._errorReporter);

  void assignmentExpression(AssignmentExpression node) {
    _checkForDeprecated(node.readElement, node.leftHandSide);
    _checkForDeprecated(node.writeElement, node.leftHandSide);
    _checkForDeprecated(node.staticElement, node);
  }

  void binaryExpression(BinaryExpression node) {
    _checkForDeprecated(node.staticElement, node);
  }

  void constructorName(ConstructorName node) {
    _checkForDeprecated(node.staticElement, node);
  }

  void exportDirective(ExportDirective node) {
    _checkForDeprecated(node.uriElement, node);
  }

  void functionExpressionInvocation(FunctionExpressionInvocation node) {
    var callElement = node.staticElement;
    if (callElement is MethodElement &&
        callElement.name == FunctionElement.CALL_METHOD_NAME) {
      _checkForDeprecated(callElement, node);
    }
  }

  void importDirective(ImportDirective node) {
    _checkForDeprecated(node.uriElement, node);
  }

  void indexExpression(IndexExpression node) {
    _checkForDeprecated(node.staticElement, node);
  }

  void instanceCreationExpression(InstanceCreationExpression node) {
    _invocationArguments(
      node.constructorName.staticElement,
      node.argumentList,
    );
  }

  void methodInvocation(MethodInvocation node) {
    _invocationArguments(
      node.methodName.staticElement,
      node.argumentList,
    );
  }

  void popInDeprecated() {
    _inDeprecatedMemberStack.removeLast();
  }

  void postfixExpression(PostfixExpression node) {
    _checkForDeprecated(node.readElement, node.operand);
    _checkForDeprecated(node.writeElement, node.operand);
    _checkForDeprecated(node.staticElement, node);
  }

  void prefixExpression(PrefixExpression node) {
    _checkForDeprecated(node.readElement, node.operand);
    _checkForDeprecated(node.writeElement, node.operand);
    _checkForDeprecated(node.staticElement, node);
  }

  void pushInDeprecatedMetadata(List<Annotation> metadata) {
    var hasDeprecated = _hasDeprecatedAnnotation(metadata);
    pushInDeprecatedValue(hasDeprecated);
  }

  void pushInDeprecatedValue(bool value) {
    var newValue = _inDeprecatedMemberStack.last || value;
    _inDeprecatedMemberStack.add(newValue);
  }

  void redirectingConstructorInvocation(RedirectingConstructorInvocation node) {
    _checkForDeprecated(node.staticElement, node);
    _invocationArguments(node.staticElement, node.argumentList);
  }

  void simpleIdentifier(SimpleIdentifier node) {
    // Don't report declared identifiers.
    if (node.inDeclarationContext()) {
      return;
    }

    // Report full ConstructorName, not just the constructor name.
    var parent = node.parent;
    if (parent is ConstructorName && identical(node, parent.name)) {
      return;
    }

    // Report full SuperConstructorInvocation, not just the constructor name.
    if (parent is SuperConstructorInvocation &&
        identical(node, parent.constructorName)) {
      return;
    }

    // HideCombinator is forgiving.
    if (parent is HideCombinator) {
      return;
    }

    _simpleIdentifier(node);
  }

  void superConstructorInvocation(SuperConstructorInvocation node) {
    _checkForDeprecated(node.staticElement, node);
    _invocationArguments(node.staticElement, node.argumentList);
  }

  /// Given some [element], look at the associated metadata and report the use
  /// of the member if it is declared as deprecated. If a diagnostic is reported
  /// it should be reported at the given [node].
  void _checkForDeprecated(Element? element, AstNode node) {
    if (!_isDeprecated(element)) {
      return;
    }

    if (_inDeprecatedMemberStack.last) {
      return;
    }

    if (_isLocalParameter(element, node)) {
      return;
    }

    var errorNode = node;
    var parent = node.parent;
    if (parent is AssignmentExpression && parent.leftHandSide == node) {
      if (node is SimpleIdentifier) {
        errorNode = node;
      } else if (node is PrefixedIdentifier) {
        errorNode = node.identifier;
      } else if (node is PropertyAccess) {
        errorNode = node.propertyName;
      }
    } else if (node is NamedExpression) {
      errorNode = node.name.label;
    }

    String displayName = element!.displayName;
    if (element is ConstructorElement) {
      // TODO(jwren) We should modify ConstructorElement.getDisplayName(),
      // or have the logic centralized elsewhere, instead of doing this logic
      // here.
      displayName = element.enclosingElement.displayName;
      if (element.displayName.isNotEmpty) {
        displayName = "$displayName.${element.displayName}";
      }
    } else if (element is LibraryElement) {
      displayName = element.definingCompilationUnit.source.uri.toString();
    } else if (node is MethodInvocation &&
        displayName == FunctionElement.CALL_METHOD_NAME) {
      var invokeType = node.staticInvokeType as InterfaceType;
      if (invokeType is InterfaceType) {
        var invokeClass = invokeType.element;
        displayName = "${invokeClass.name}.${element.displayName}";
      }
    }
    var library = element is LibraryElement ? element : element.library;
    var message = _deprecatedMessage(element);
    if (message == null || message.isEmpty) {
      _errorReporter.reportErrorForNode(
        _isLibraryInWorkspacePackage(library)
            ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
            : HintCode.DEPRECATED_MEMBER_USE,
        errorNode,
        [displayName],
      );
    } else {
      _errorReporter.reportErrorForNode(
        _isLibraryInWorkspacePackage(library)
            ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE
            : HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE,
        errorNode,
        [displayName, message],
      );
    }
  }

  void _invocationArguments(Element? element, ArgumentList arguments) {
    element = element?.declaration;
    if (element is ExecutableElement) {
      _visitParametersAndArguments(
        element.parameters,
        arguments.arguments,
        (parameter, argument) {
          if (parameter.isOptional) {
            _checkForDeprecated(parameter, argument);
          }
        },
      );
    }
  }

  bool _isLibraryInWorkspacePackage(LibraryElement? library) {
    // Better to not make a big claim that they _are_ in the same package,
    // if we were unable to determine what package [_currentLibrary] is in.
    if (_workspacePackage == null || library == null) {
      return false;
    }
    return _workspacePackage!.contains(library.source);
  }

  void _simpleIdentifier(SimpleIdentifier identifier) {
    _checkForDeprecated(identifier.staticElement, identifier);
  }

  /// Return the message in the deprecated annotation on the given [element], or
  /// `null` if the element doesn't have a deprecated annotation or if the
  /// annotation does not have a message.
  static String? _deprecatedMessage(Element element) {
    // Implicit getters/setters.
    if (element.isSynthetic && element is PropertyAccessorElement) {
      element = element.variable;
    }
    var annotation = element.metadata.firstWhereOrNull((e) => e.isDeprecated);
    if (annotation == null || annotation.element is PropertyAccessorElement) {
      return null;
    }
    var constantValue = annotation.computeConstantValue();
    return constantValue?.getField('message')?.toStringValue() ??
        constantValue?.getField('expires')?.toStringValue();
  }

  static bool _hasDeprecatedAnnotation(List<Annotation> annotations) {
    for (var i = 0; i < annotations.length; i++) {
      if (annotations[i].elementAnnotation!.isDeprecated) {
        return true;
      }
    }
    return false;
  }

  static bool _isDeprecated(Element? element) {
    if (element == null) {
      return false;
    }

    if (element is PropertyAccessorElement && element.isSynthetic) {
      // TODO(brianwilkerson) Why isn't this the implementation for PropertyAccessorElement?
      Element variable = element.variable;
      return variable.hasDeprecated;
    }
    return element.hasDeprecated;
  }

  /// Return `true` if [element] is a [ParameterElement] declared in [node].
  static bool _isLocalParameter(Element? element, AstNode? node) {
    if (element is ParameterElement) {
      var definingFunction = element.enclosingElement as ExecutableElement;

      for (; node != null; node = node.parent) {
        if (node is ConstructorDeclaration) {
          if (node.declaredElement == definingFunction) {
            return true;
          }
        } else if (node is FunctionExpression) {
          if (node.declaredElement == definingFunction) {
            return true;
          }
        } else if (node is MethodDeclaration) {
          if (node.declaredElement == definingFunction) {
            return true;
          }
        }
      }
    }
    return false;
  }

  static void _visitParametersAndArguments(
    List<ParameterElement> parameters,
    List<Expression> arguments,
    void Function(ParameterElement, Expression) f,
  ) {
    Map<String, ParameterElement>? namedParameters;

    var positionalIndex = 0;
    for (var argument in arguments) {
      if (argument is NamedExpression) {
        if (namedParameters == null) {
          namedParameters = {};
          for (var parameter in parameters) {
            if (parameter.isNamed) {
              namedParameters[parameter.name] = parameter;
            }
          }
        }
        var name = argument.name.label.name;
        var parameter = namedParameters[name];
        if (parameter != null) {
          f(parameter, argument);
        }
      } else {
        if (positionalIndex < parameters.length) {
          var parameter = parameters[positionalIndex++];
          if (parameter.isPositional) {
            f(parameter, argument);
          }
        }
      }
    }
  }
}
