// 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/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// Helper for resolving [ForStatement]s and [ForElement]s.
class ForResolver {
  final ResolverVisitor _resolver;

  ForResolver({
    required ResolverVisitor resolver,
  }) : _resolver = resolver;

  TypeSystemImpl get _typeSystem => _resolver.typeSystem;

  void resolveElement(ForElementImpl node, CollectionLiteralContext? context) {
    var forLoopParts = node.forLoopParts;
    void visitBody() {
      node.body.resolveElement(_resolver, context);
    }

    if (forLoopParts is ForPartsImpl) {
      _forParts(node, forLoopParts, visitBody);
    } else if (forLoopParts is ForEachPartsImpl) {
      _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
    }
  }

  void resolveStatement(ForStatementImpl node) {
    _resolver.checkUnreachableNode(node);

    var forLoopParts = node.forLoopParts;
    void visitBody() {
      node.body.accept(_resolver);
    }

    if (forLoopParts is ForPartsImpl) {
      _forParts(node, forLoopParts, visitBody);
    } else if (forLoopParts is ForEachPartsImpl) {
      _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
    }
  }

  /// Given an iterable expression from a foreach loop, attempt to infer
  /// a type for the elements being iterated over.  Inference is based
  /// on the type of the iterator or stream over which the foreach loop
  /// is defined.
  DartType? _computeForEachElementType(Expression iterable, bool isAsync) {
    var iterableType = iterable.staticType;
    if (iterableType == null) return null;
    iterableType = _typeSystem.resolveToBound(iterableType);

    ClassElement iteratedElement = isAsync
        ? _resolver.typeProvider.streamElement
        : _resolver.typeProvider.iterableElement;

    var iteratedType = iterableType.asInstanceOf(iteratedElement);

    if (iteratedType != null) {
      var elementType = iteratedType.typeArguments.single;
      elementType = _resolver.toLegacyTypeIfOptOut(elementType);
      return elementType;
    } else {
      return null;
    }
  }

  void _forEachParts(AstNode node, bool isAsync, ForEachParts forEachParts,
      void Function() visitBody) {
    Expression iterable = forEachParts.iterable;
    DeclaredIdentifier? loopVariable;
    SimpleIdentifier? identifier;
    Element? identifierElement;
    if (forEachParts is ForEachPartsWithDeclaration) {
      loopVariable = forEachParts.loopVariable;
    } else if (forEachParts is ForEachPartsWithIdentifier) {
      identifier = forEachParts.identifier;
      // TODO(scheglov) replace with lexical lookup
      identifier.accept(_resolver);
      AssignmentExpressionShared(
        resolver: _resolver,
      ).checkFinalAlreadyAssigned(identifier);
    }

    DartType? valueType;
    if (loopVariable != null) {
      var typeAnnotation = loopVariable.type;
      valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
    }
    if (identifier != null) {
      identifierElement = identifier.staticElement;
      if (identifierElement is VariableElement) {
        valueType = _resolver.localVariableTypeProvider
            .getType(identifier, isRead: false);
      } else if (identifierElement is PropertyAccessorElement) {
        var parameters = identifierElement.parameters;
        if (parameters.isNotEmpty) {
          valueType = parameters[0].type;
        }
      }
    }
    InterfaceType? targetType;
    if (valueType != null) {
      targetType = isAsync
          ? _resolver.typeProvider.streamType(valueType)
          : _resolver.typeProvider.iterableType(valueType);
    }

    _resolver.analyzeExpression(iterable, targetType);
    iterable = forEachParts.iterable;

    _resolver.nullableDereferenceVerifier.expression(
      CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR,
      iterable,
    );

    loopVariable?.accept(_resolver);
    var elementType = _computeForEachElementType(iterable, isAsync);
    if (loopVariable != null &&
        elementType != null &&
        loopVariable.type == null) {
      var loopVariableElement =
          loopVariable.declaredElement as LocalVariableElementImpl;
      loopVariableElement.type = elementType;
    }

    if (loopVariable != null) {
      _resolver.flowAnalysis.flow?.declare(loopVariable.declaredElement!, true);
    }

    _resolver.flowAnalysis.flow?.forEach_bodyBegin(node);
    if (identifierElement is PromotableElement &&
        forEachParts is ForEachPartsWithIdentifier) {
      _resolver.flowAnalysis.flow?.write(forEachParts, identifierElement,
          elementType ?? DynamicTypeImpl.instance, null);
    }

    visitBody();

    _resolver.flowAnalysis.flow?.forEach_end();
  }

  void _forParts(AstNode node, ForParts forParts, void Function() visitBody) {
    if (forParts is ForPartsWithDeclarations) {
      forParts.variables.accept(_resolver);
    } else if (forParts is ForPartsWithExpression) {
      forParts.initialization?.accept(_resolver);
    }

    _resolver.flowAnalysis.for_conditionBegin(node);

    var condition = forParts.condition;
    if (condition != null) {
      _resolver.analyzeExpression(condition, _resolver.typeProvider.boolType);
      condition = forParts.condition!;
      var whyNotPromoted =
          _resolver.flowAnalysis.flow?.whyNotPromoted(condition);
      _resolver.boolExpressionVerifier
          .checkForNonBoolCondition(condition, whyNotPromoted: whyNotPromoted);
    }

    _resolver.flowAnalysis.for_bodyBegin(node, condition);
    visitBody();

    _resolver.flowAnalysis.flow?.for_updaterBegin();
    forParts.updaters.accept(_resolver);

    _resolver.flowAnalysis.flow?.for_end();
  }
}
