// 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/ast/token.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/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// Helper for resolving [PostfixExpression]s.
class PostfixExpressionResolver {
  final ResolverVisitor _resolver;
  final TypePropertyResolver _typePropertyResolver;
  final InvocationInferenceHelper _inferenceHelper;
  final AssignmentExpressionShared _assignmentShared;

  PostfixExpressionResolver({
    required ResolverVisitor resolver,
  })  : _resolver = resolver,
        _typePropertyResolver = resolver.typePropertyResolver,
        _inferenceHelper = resolver.inferenceHelper,
        _assignmentShared = AssignmentExpressionShared(
          resolver: resolver,
        );

  ErrorReporter get _errorReporter => _resolver.errorReporter;

  bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;

  TypeSystemImpl get _typeSystem => _resolver.typeSystem;

  void resolve(PostfixExpressionImpl node, {required DartType? contextType}) {
    if (node.operator.type == TokenType.BANG) {
      _resolveNullCheck(node, contextType: contextType);
      return;
    }

    var operandResolution = _resolver.resolveForWrite(
      node: node.operand,
      hasRead: true,
    );

    var readElement = operandResolution.readElement;
    var writeElement = operandResolution.writeElement;

    var operand = node.operand;
    _resolver.setReadElement(operand, readElement);
    _resolver.setWriteElement(operand, writeElement);
    _resolver.migrationResolutionHooks
        ?.setCompoundAssignmentExpressionTypes(node);

    // TODO(scheglov) Use VariableElement and do in resolveForWrite() ?
    _assignmentShared.checkFinalAlreadyAssigned(operand);

    var receiverType = node.readType!;
    _resolve1(node, receiverType);
    _resolve2(node, receiverType, contextType: contextType);
  }

  /// Check that the result [type] of a prefix or postfix `++` or `--`
  /// expression is assignable to the write type of the [operand].
  ///
  /// TODO(scheglov) this is duplicate
  void _checkForInvalidAssignmentIncDec(
      PostfixExpression node, Expression operand, DartType type) {
    var operandWriteType = node.writeType!;
    if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
      _resolver.errorReporter.reportErrorForNode(
        CompileTimeErrorCode.INVALID_ASSIGNMENT,
        node,
        [type, operandWriteType],
      );
    }
  }

  /// Compute the static return type of the method or function represented by the given element.
  ///
  /// @param element the element representing the method or function invoked by the given node
  /// @return the static return type that was computed
  ///
  /// TODO(scheglov) this is duplicate
  DartType _computeStaticReturnType(Element? element) {
    if (element is PropertyAccessorElement) {
      //
      // This is a function invocation expression disguised as something else.
      // We are invoking a getter and then invoking the returned function.
      //
      FunctionType propertyType = element.type;
      return _resolver.inferenceHelper.computeInvokeReturnType(
        propertyType.returnType,
      );
    } else if (element is ExecutableElement) {
      return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
    }
    return DynamicTypeImpl.instance;
  }

  /// Return the name of the method invoked by the given postfix [expression].
  String _getPostfixOperator(PostfixExpression expression) {
    if (expression.operator.type == TokenType.PLUS_PLUS) {
      return TokenType.PLUS.lexeme;
    } else if (expression.operator.type == TokenType.MINUS_MINUS) {
      return TokenType.MINUS.lexeme;
    } else {
      throw UnsupportedError(
          'Unsupported postfix operator ${expression.operator.lexeme}');
    }
  }

  void _resolve1(PostfixExpressionImpl node, DartType receiverType) {
    Expression operand = node.operand;

    if (identical(receiverType, NeverTypeImpl.instance)) {
      _resolver.errorReporter.reportErrorForNode(
        HintCode.RECEIVER_OF_TYPE_NEVER,
        operand,
      );
      return;
    }

    String methodName = _getPostfixOperator(node);
    var result = _typePropertyResolver.resolve(
      receiver: operand,
      receiverType: receiverType,
      name: methodName,
      propertyErrorEntity: node.operator,
      nameErrorEntity: operand,
    );
    node.staticElement = result.getter as MethodElement?;
    if (result.needsGetterError) {
      if (operand is SuperExpression) {
        _errorReporter.reportErrorForToken(
          CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR,
          node.operator,
          [methodName, receiverType],
        );
      } else {
        _errorReporter.reportErrorForToken(
          CompileTimeErrorCode.UNDEFINED_OPERATOR,
          node.operator,
          [methodName, receiverType],
        );
      }
    }
  }

  void _resolve2(PostfixExpressionImpl node, DartType receiverType,
      {required DartType? contextType}) {
    Expression operand = node.operand;

    if (identical(receiverType, NeverTypeImpl.instance)) {
      _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance,
          contextType: contextType);
    } else {
      DartType operatorReturnType;
      if (receiverType.isDartCoreInt) {
        // No need to check for `intVar++`, the result is `int`.
        operatorReturnType = receiverType;
      } else {
        var operatorElement = node.staticElement;
        operatorReturnType = _computeStaticReturnType(operatorElement);
        _checkForInvalidAssignmentIncDec(node, operand, operatorReturnType);
      }
      if (operand is SimpleIdentifier) {
        var element = operand.staticElement;
        if (element is PromotableElement) {
          _resolver.flowAnalysis.flow
              ?.write(node, element, operatorReturnType, null);
        }
      }
    }

    _inferenceHelper.recordStaticType(node, receiverType,
        contextType: contextType);
    _resolver.nullShortingTermination(node);
  }

  void _resolveNullCheck(PostfixExpressionImpl node,
      {required DartType? contextType}) {
    var operand = node.operand;

    if (operand is SuperExpression) {
      _resolver.errorReporter.reportErrorForNode(
        ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR,
        node,
      );
      _inferenceHelper.recordStaticType(operand, DynamicTypeImpl.instance,
          contextType: contextType);
      _inferenceHelper.recordStaticType(node, DynamicTypeImpl.instance,
          contextType: contextType);
      return;
    }

    if (contextType != null && _isNonNullableByDefault) {
      contextType = _typeSystem.makeNullable(contextType);
    }

    _resolver.analyzeExpression(operand, contextType);
    operand = node.operand;

    var operandType = operand.typeOrThrow;

    var type = _typeSystem.promoteToNonNull(operandType);
    _inferenceHelper.recordStaticType(node, type, contextType: contextType);

    _resolver.nullShortingTermination(node);
    _resolver.flowAnalysis.flow?.nonNullAssert_end(operand);
  }
}
