// Copyright (c) 2015, 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/analyzer.dart' as analyzer;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/element/type.dart' show DartType;
import 'package:analyzer/src/dart/ast/ast.dart' show FunctionBodyImpl;
import 'package:analyzer/src/dart/ast/utilities.dart' show NodeReplacer;
import 'package:analyzer/src/dart/element/type.dart' show DynamicTypeImpl;
import 'package:analyzer/src/generated/parser.dart' show ResolutionCopier;
import 'package:analyzer/src/task/strong/ast_properties.dart' as ast_properties;

import 'ast_builder.dart';
import 'element_helpers.dart' show isInlineJS;

// This class implements a pass which modifies (in place) the ast replacing
// abstract coercion nodes with their dart implementations.
class CoercionReifier extends analyzer.GeneralizingAstVisitor<void> {
  final cloner = _TreeCloner();

  CoercionReifier._();

  /// Transforms the given compilation units, and returns a new AST with
  /// explicit coercion nodes in appropriate places.
  static List<CompilationUnit> reify(List<CompilationUnit> units) {
    var cr = CoercionReifier._();
    return units.map(cr.visitCompilationUnit).toList(growable: false);
  }

  /// True if the `as` [node] is a required runtime check for soundness.
  // TODO(sra): Find a better way to recognize reified coercion, since we
  // can't set the isSynthetic attribute.
  static bool isImplicit(AsExpression node) => node.asOperator.offset == 0;

  /// Creates an implicit cast for expression [e] to [toType].
  static Expression castExpression(Expression e, DartType toType) {
    // We use an empty name in the AST, because the JS code generator only cares
    // about the target type. It does not look at the AST name.
    var typeName = astFactory.typeName(ast.identifierFromString(''), null);
    typeName.type = toType;
    var cast = ast.asExpression(e, typeName);
    cast.staticType = toType;
    return cast;
  }

  @override
  CompilationUnit visitCompilationUnit(CompilationUnit node) {
    if (ast_properties.hasImplicitCasts(node)) {
      // Clone compilation unit, so we don't modify the originals.
      node = _clone(node);
      super.visitCompilationUnit(node);
    }
    return node;
  }

  @override
  visitExpression(Expression node) {
    node.visitChildren(this);

    var castType = ast_properties.getImplicitCast(node);
    if (castType != null) {
      _replaceNode(node.parent, node, castExpression(node, castType));
    }
  }

  @override
  visitMethodInvocation(MethodInvocation node) {
    if (isInlineJS(node.methodName.staticElement)) {
      // Don't cast our inline-JS code in SDK.
      ast_properties.setImplicitCast(node, null);
    }
    visitExpression(node);
  }

  @override
  visitParenthesizedExpression(ParenthesizedExpression node) {
    super.visitParenthesizedExpression(node);
    node.staticType = node.expression.staticType;
  }

  @override
  visitForEachStatement(ForEachStatement node) {
    // Visit other children.
    node.iterable.accept(this);
    node.body.accept(this);

    // If needed, assert a cast inside the body before the variable is read.
    var variable = node.identifier ?? node.loopVariable.identifier;
    var castType = ast_properties.getImplicitCast(variable);
    if (castType != null) {
      // Build the cast. We will place this cast in the body, so need to clone
      // the variable's AST node and clear out its static type (otherwise we
      // will optimize away the cast).
      var cast = castExpression(
          _clone(variable)..staticType = DynamicTypeImpl.instance, castType);

      var body = node.body;
      var blockBody = <Statement>[ast.expressionStatement(cast)];
      if (body is Block) {
        blockBody.addAll(body.statements);
      } else {
        blockBody.add(body);
      }
      _replaceNode(node, body, ast.block(blockBody));
    }
  }

  void _replaceNode(AstNode parent, AstNode oldNode, AstNode newNode) {
    if (!identical(oldNode, newNode)) {
      var replaced = parent.accept(NodeReplacer(oldNode, newNode));
      // It looks like NodeReplacer will always return true.
      // It does throw IllegalArgumentException though, if child is not found.
      assert(replaced);
    }
  }

  T _clone<T extends AstNode>(T node) {
    var copy = node.accept(cloner) as T;
    ResolutionCopier.copyResolutionData(node, copy);
    return copy;
  }
}

class _TreeCloner extends analyzer.AstCloner {
  void _cloneProperties(AstNode clone, AstNode node) {
    if (clone is Expression && node is Expression) {
      ast_properties.setImplicitCast(
          clone, ast_properties.getImplicitCast(node));
      ast_properties.setImplicitOperationCast(
          clone, ast_properties.getImplicitOperationCast(node));
      ast_properties.setIsDynamicInvoke(
          clone, ast_properties.isDynamicInvoke(node));
    }
    if (clone is Declaration && node is Declaration) {
      ast_properties.setClassCovariantParameters(
          clone, ast_properties.getClassCovariantParameters(node));
      ast_properties.setSuperclassCovariantParameters(
          clone, ast_properties.getSuperclassCovariantParameters(node));
    }
  }

  @override
  E cloneNode<E extends AstNode>(E node) {
    var clone = super.cloneNode(node);
    _cloneProperties(clone, node);
    return clone;
  }

  @override
  List<E> cloneNodeList<E extends AstNode>(List<E> list) {
    var clone = super.cloneNodeList(list);
    for (int i = 0, len = list.length; i < len; i++) {
      _cloneProperties(clone[i], list[i]);
    }
    return clone;
  }

  // TODO(jmesserly): ResolutionCopier is not copying this yet.
  @override
  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) {
    var clone = super.visitBlockFunctionBody(node);
    (clone as FunctionBodyImpl).localVariableInfo =
        (node as FunctionBodyImpl).localVariableInfo;
    return clone;
  }

  @override
  ExpressionFunctionBody visitExpressionFunctionBody(
      ExpressionFunctionBody node) {
    var clone = super.visitExpressionFunctionBody(node);
    (clone as FunctionBodyImpl).localVariableInfo =
        (node as FunctionBodyImpl).localVariableInfo;
    return clone;
  }

  // TODO(jmesserly): workaround for
  // https://github.com/dart-lang/sdk/issues/26368
  @override
  TypeName visitTypeName(TypeName node) {
    var clone = super.visitTypeName(node);
    clone.type = node.type;
    return clone;
  }
}
