// Copyright (c) 2016, 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.

library kernel.transformations.reify.transformation.transformer;

import '../analysis/program_analysis.dart';
import 'package:kernel/ast.dart';
import 'binding.dart' show RuntimeLibrary;
import 'builder.dart' show RuntimeTypeSupportBuilder;
import 'dart:collection' show LinkedHashMap;
import '../asts.dart';

export 'binding.dart' show RuntimeLibrary;
export 'builder.dart' show RuntimeTypeSupportBuilder;

enum RuntimeTypeStorage {
  none,
  inheritedField,
  field,
  getter,
}

class TransformationContext {
  /// Describes how the runtime type is stored on the object.
  RuntimeTypeStorage runtimeTypeStorage;

  /// Field added to store the runtime type if [runtimeType] is
  /// [RuntimeTypeStorage.field].
  Field runtimeTypeField;

  /// The parameter for the type information introduced to the constructor or
  /// to static initializers.
  VariableDeclaration parameter;

  /// A ordered collection of fields together with their initializers rewritten
  /// to static initializer functions that can be used in the constructor's
  /// initializer list.
  /// The order is important because of possible side-effects in the
  /// initializers.
  LinkedHashMap<Field, Procedure> initializers;

  // `true` if the visitor currently is in a field initializer, a initializer
  // list of a constructor, or the body of a factory method. In these cases,
  // type argument access is different than in an instance context, since `this`
  // is not available.
  bool inInitializer = false;

  String toString() => "s: ${runtimeTypeStorage} f: $runtimeTypeField,"
      " p: $parameter, i: $inInitializer";
}

abstract class DebugTrace {
  static const bool debugTrace = false;

  static const int lineLength = 80;

  TransformationContext get context;

  String getNodeLevel(TreeNode node) {
    String level = "";
    while (node != null && node is! Library) {
      level = " $level";
      node = node.parent;
    }
    return level;
  }

  String shorten(String s) {
    return s.length > lineLength ? s.substring(0, lineLength) : s;
  }

  void trace(TreeNode node) {
    if (debugTrace) {
      String nodeText = node.toString().replaceAll("\n", " ");
      print(shorten("trace:${getNodeLevel(node)}$context"
          " [${node.runtimeType}] $nodeText"));
    }
  }
}

/// Rewrites a tree to remove generic types and runtime type checks and replace
/// them with Dart objects.
///
/// Runtime types are stored in a field/getter called [runtimeTypeName] on the
/// object, which for parameterized classes is initialized in the constructor.
//  TODO(karlklose):
//  - add a scoped namer
//  - rewrite types (supertypes, implemented types)
//  - rewrite as
class ReifyVisitor extends Transformer with DebugTrace {
  final RuntimeLibrary rtiLibrary;
  final RuntimeTypeSupportBuilder builder;
  final ProgramKnowledge knowledge;

  ReifyVisitor(this.rtiLibrary, this.builder, this.knowledge,
      [this.libraryToTransform]);

  /// If not null, the transformation will only be applied to classes declared
  /// in this library.
  final Library libraryToTransform;

  // TODO(karlklose): find a way to get rid of this state in the visitor.
  TransformationContext context;

  bool libraryShouldBeTransformed(Library library) {
    return libraryToTransform == null || libraryToTransform == library;
  }

  bool needsTypeInformation(Class cls) {
    return !isObject(cls) &&
        !rtiLibrary.contains(cls) &&
        libraryShouldBeTransformed(cls.enclosingLibrary);
  }

  bool usesTypeGetter(Class cls) {
    return cls.typeParameters.isEmpty;
  }

  bool isObject(Class cls) {
    // TODO(karlklose): use [CoreTypes].
    return "$cls" == 'dart.core::Object';
  }

  Initializer addTypeAsArgument(initializer) {
    assert(initializer is SuperInitializer ||
        initializer is RedirectingInitializer);
    Class cls = getEnclosingClass(initializer.target);
    if (needsTypeInformation(cls) && !usesTypeGetter(cls)) {
      // If the current class uses a getter for type information, we did not add
      // a parameter to the constructor, but we can pass `null` as the value to
      // initialize the type field, since it will be shadowed by the getter.
      Expression type = (context.parameter != null)
          ? new VariableGet(context.parameter)
          : new NullLiteral();
      builder.insertAsFirstArgument(initializer.arguments, type);
    }
    return initializer;
  }

  Expression interceptInstantiation(
      InvocationExpression invocation, Member target) {
    Class targetClass = target.parent;
    Library targetLibrary = targetClass.parent;
    Library currentLibrary = getEnclosingLibrary(invocation);
    if (libraryShouldBeTransformed(currentLibrary) &&
        !libraryShouldBeTransformed(targetLibrary) &&
        !rtiLibrary.contains(target)) {
      return builder.attachTypeToConstructorInvocation(invocation, target);
    }
    return invocation;
  }

  Expression createRuntimeType(DartType type) {
    if (context?.inInitializer == true) {
      // In initializer context, the instance type is provided in
      // `context.parameter` as there is no `this`.
      return builder.createRuntimeType(type, typeContext: context.parameter);
    } else {
      return builder.createRuntimeType(type);
    }
  }

  TreeNode defaultTreeNode(TreeNode node) {
    trace(node);
    return super.defaultTreeNode(node);
  }

  Expression visitStaticInvocation(StaticInvocation invocation) {
    trace(invocation);

    invocation.transformChildren(this);

    Procedure target = invocation.target;
    if (target == rtiLibrary.reifyFunction) {
      /// Rewrite calls to reify(TypeLiteral) to a reified type.
      TypeLiteral literal = invocation.arguments.positional.single;
      return createRuntimeType(literal.type);
    } else if (target.kind == ProcedureKind.Factory) {
      // Intercept calls to factories of classes we do not transform
      return interceptInstantiation(invocation, target);
    }
    return invocation;
  }

  Library visitLibrary(Library library) {
    trace(library);

    if (libraryShouldBeTransformed(library)) {
      library.transformChildren(this);
    }
    return library;
  }

  Expression visitConstructorInvocation(ConstructorInvocation invocation) {
    invocation.transformChildren(this);
    return interceptInstantiation(invocation, invocation.target);
  }

  Member getStaticInvocationTarget(InvocationExpression invocation) {
    if (invocation is ConstructorInvocation) {
      return invocation.target;
    } else if (invocation is StaticInvocation) {
      return invocation.target;
    } else {
      throw "Unexpected InvocationExpression $invocation.";
    }
  }

  bool isInstantiation(TreeNode invocation) {
    return invocation is ConstructorInvocation ||
        invocation is StaticInvocation &&
            invocation.target.kind == ProcedureKind.Factory;
  }

  bool isTypeVariable(DartType type) => type is TypeParameterType;

  /// Add the runtime type as an extra argument to constructor invocations.
  Arguments visitArguments(Arguments arguments) {
    trace(arguments);

    arguments.transformChildren(this);
    TreeNode parent = arguments.parent;
    if (isInstantiation(parent)) {
      Class targetClass = getEnclosingClass(getStaticInvocationTarget(parent));
      // Do not add the extra argument if the class does not need a type member
      // or if it can be implemented as a getter.
      if (!needsTypeInformation(targetClass) || usesTypeGetter(targetClass)) {
        return arguments;
      }

      List<DartType> typeArguments = arguments.types;

      Expression type =
          createRuntimeType(new InterfaceType(targetClass, typeArguments));

      builder.insertAsFirstArgument(arguments, type);
    }
    return arguments;
  }

  Field visitField(Field field) {
    trace(field);

    visitDartType(field.type);
    for (Expression annotation in field.annotations) {
      annotation.accept(this);
    }
    // Do not visit initializers, they have already been transformed when the
    // class was handled.
    return field;
  }

  /// Go through all initializers of fields and record a static initializer
  /// function, if necessary.
  void rewriteFieldInitializers(Class cls) {
    assert(context != null);
    context.initializers = new LinkedHashMap<Field, Procedure>();
    List<Field> fields = cls.fields;
    bool initializerRewritten = false;
    for (Field field in fields) {
      if (!initializerRewritten && knowledge.usedParameters(field).isEmpty) {
        // This field needs no static initializer.
        continue;
      }

      Expression initializer = field.initializer;
      if (initializer == null || field.isStatic) continue;
      // Declare a new variable that holds the type information and can be
      // used to access type variables in initializer context.
      // TODO(karlklose): some fields do not need the parameter.
      VariableDeclaration typeObject = new VariableDeclaration(r"$type");
      context.parameter = typeObject;
      context.inInitializer = true;
      // Translate the initializer while keeping track of whether there was
      // already an initializers that required type information in
      // [typeVariableUsedInInitializer].
      initializer = initializer.accept(this);
      context.parameter = null;
      context.inInitializer = false;
      // Create a static initializer function from the translated initializer
      // expression and record it.
      Name name = new Name("\$init\$${field.name.name}");
      Statement body = new ReturnStatement(initializer);
      Procedure staticInitializer = new Procedure(
          name,
          ProcedureKind.Method,
          new FunctionNode(body,
              positionalParameters: <VariableDeclaration>[typeObject]),
          isStatic: true,
          fileUri: cls.fileUri);
      context.initializers[field] = staticInitializer;
      // Finally, remove the initializer from the field.
      field.initializer = null;
    }
  }

  bool inheritsTypeProperty(Class cls) {
    assert(needsTypeInformation(cls));
    Class superclass = cls.superclass;
    return needsTypeInformation(superclass);
  }

  Class visitClass(Class cls) {
    trace(cls);

    if (needsTypeInformation(cls)) {
      context = new TransformationContext();
      List<TypeParameter> typeParameters = cls.typeParameters;
      if (usesTypeGetter(cls)) {
        assert(typeParameters.isEmpty);
        context.runtimeTypeStorage = RuntimeTypeStorage.getter;
        Member getter = builder.createGetter(rtiLibrary.runtimeTypeName,
            createRuntimeType(cls.rawType), cls, rtiLibrary.typeType);
        cls.addMember(getter);
      } else if (!inheritsTypeProperty(cls)) {
        context.runtimeTypeStorage = RuntimeTypeStorage.field;
        // TODO(karlklose): should we add the field to [Object]?
        context.runtimeTypeField = new Field(rtiLibrary.runtimeTypeName,
            fileUri: cls.fileUri, isFinal: true, type: rtiLibrary.typeType);
        cls.addMember(context.runtimeTypeField);
      } else {
        context.runtimeTypeStorage = RuntimeTypeStorage.inheritedField;
      }

      for (int i = 0; i < typeParameters.length; ++i) {
        TypeParameter variable = typeParameters[i];
        cls.addMember(builder.createTypeVariableGetter(cls, variable, i));
      }

      // Tag the class as supporting the runtime type getter.
      InterfaceType interfaceTypeForSupertype =
          new InterfaceType(rtiLibrary.markerClass);
      cls.implementedTypes.add(new Supertype(
          interfaceTypeForSupertype.classNode,
          interfaceTypeForSupertype.typeArguments));

      // Before transforming the parts of the class declaration, rewrite field
      // initializers that use type variables (or that would be called after one
      // that does) to static functions that can be used from constructors.
      rewriteFieldInitializers(cls);

      // Add properties for declaration tests.
      for (Class test in knowledge.classTests) {
        if (test == rtiLibrary.markerClass) continue;

        Procedure tag = builder.createGetter(
            builder.getTypeTestTagName(test),
            new BoolLiteral(isSuperClass(test, cls)),
            cls,
            builder.coreTypes.boolClass.rawType);
        cls.addMember(tag);
      }

      // Add a runtimeType getter.
      if (!usesTypeGetter(cls) && !inheritsTypeProperty(cls)) {
        cls.addMember(new Procedure(
            new Name("runtimeType"),
            ProcedureKind.Getter,
            new FunctionNode(
                new ReturnStatement(new DirectPropertyGet(
                    new ThisExpression(), context.runtimeTypeField)),
                returnType: builder.coreTypes.typeClass.rawType),
            fileUri: cls.fileUri));
      }
    }

    cls.transformChildren(this);

    // Add the static initializer functions. They have already been transformed.
    if (context?.initializers != null) {
      context.initializers.forEach((_, Procedure initializer) {
        cls.addMember(initializer);
      });
    }

    // TODO(karlklose): clear type arguments later, the order of class
    // transformations otherwise influences the result.
    // cls.typeParameters.clear();
    context = null;
    return cls;
  }

  // TODO(karlklose): replace with a structure that can answer also the question
  // which tags must be overriden due to different values.
  /// Returns `true` if [a] is a declaration used in a supertype of [b].
  bool isSuperClass(Class a, Class b) {
    if (b == null) return false;
    if (a == b) return true;

    if (isSuperClass(a, b.superclass)) {
      return true;
    }

    Iterable<Class> interfaceClasses = b.implementedTypes
        .map((Supertype type) => type.classNode)
        .where((Class cls) => cls != rtiLibrary.markerClass);
    return interfaceClasses
        .any((Class declaration) => isSuperClass(a, declaration));
  }

  bool isConstructorOrFactory(TreeNode node) {
    return isFactory(node) || node is Constructor;
  }

  bool isFactory(TreeNode node) {
    return node is Procedure && node.kind == ProcedureKind.Factory;
  }

  bool needsParameterForRuntimeType(TreeNode node) {
    if (!isConstructorOrFactory(node)) return false;

    RuntimeTypeStorage access = context.runtimeTypeStorage;
    assert(access != RuntimeTypeStorage.none);
    return access == RuntimeTypeStorage.field ||
        access == RuntimeTypeStorage.inheritedField;
  }

  FunctionNode visitFunctionNode(FunctionNode node) {
    trace(node);

    // If we have a [TransformationContext] with a runtime type field and we
    // translate a constructor or factory, we need a parameter that the code of
    // initializers or the factory body can use to access type arguments.
    // The parameter field in the context will be reset in the visit-method of
    // the parent.
    if (context != null && needsParameterForRuntimeType(node.parent)) {
      assert(context.parameter == null);
      // Create the parameter and insert it as the function's first parameter.
      context.parameter = new VariableDeclaration(
          rtiLibrary.runtimeTypeName.name,
          type: rtiLibrary.typeType);
      context.parameter.parent = node;
      node.positionalParameters.insert(0, context.parameter);
      node.requiredParameterCount++;
    }
    node.transformChildren(this);
    return node;
  }

  SuperInitializer visitSuperInitializer(SuperInitializer initializer) {
    initializer.transformChildren(this);
    return addTypeAsArgument(initializer);
  }

  RedirectingInitializer visitRedirectingInitializer(
      RedirectingInitializer initializer) {
    initializer.transformChildren(this);
    return addTypeAsArgument(initializer);
  }

  Procedure visitProcedure(Procedure procedure) {
    trace(procedure);

    transformList(procedure.annotations, this, procedure.parent);
    // Visit the function body in a initializing context, if it is a factory.
    context?.inInitializer = isFactory(procedure);
    procedure.function?.accept(this);
    context?.inInitializer = false;

    context?.parameter = null;
    return procedure;
  }

  Constructor visitConstructor(Constructor constructor) {
    trace(constructor);

    transformList(constructor.annotations, this, constructor);
    if (constructor.function != null) {
      constructor.function = constructor.function.accept(this);
      constructor.function?.parent = constructor;
    }

    context?.inInitializer = true;
    transformList(constructor.initializers, this, constructor);
    context?.inInitializer = false;

    if (context != null) {
      if (context.runtimeTypeStorage == RuntimeTypeStorage.field) {
        // Initialize the runtime type field with value given in the additional
        // constructor parameter.
        assert(context.parameter != null);
        Initializer initializer = new FieldInitializer(
            context.runtimeTypeField, new VariableGet(context.parameter));
        initializer.parent = constructor;
        constructor.initializers.insert(0, initializer);
      }
      if (context.initializers != null) {
        // For each field that needed a static initializer function, initialize
        // the field by calling the function.
        List<Initializer> fieldInitializers = <Initializer>[];
        context.initializers.forEach((Field field, Procedure initializer) {
          assert(context.parameter != null);
          Arguments argument =
              new Arguments(<Expression>[new VariableGet(context.parameter)]);
          fieldInitializers.add(new FieldInitializer(
              field, new StaticInvocation(initializer, argument)));
        });
        constructor.initializers.insertAll(0, fieldInitializers);
      }
      context.parameter = null;
    }

    return constructor;
  }

  /// Returns `true` if the given type can be tested using type test tags.
  ///
  /// This implies that there are no subtypes of the [type] that are not
  /// transformed.
  bool typeSupportsTagTest(InterfaceType type) {
    return needsTypeInformation(type.classNode);
  }

  Expression visitIsExpression(IsExpression expression) {
    trace(expression);

    expression.transformChildren(this);

    if (getEnclosingLibrary(expression) == rtiLibrary.interceptorsLibrary) {
      // In the interceptor library we need actual is-checks at the moment.
      return expression;
    }

    Expression target = expression.operand;
    DartType type = expression.type;

    if (type is InterfaceType && typeSupportsTagTest(type)) {
      assert(knowledge.classTests.contains(type.classNode));
      bool checkArguments =
          type.typeArguments.any((DartType type) => type is! DynamicType);
      Class declaration = type.classNode;
      VariableDeclaration typeExpression =
          new VariableDeclaration(null, initializer: createRuntimeType(type));
      VariableDeclaration targetValue =
          new VariableDeclaration(null, initializer: target);
      Expression markerClassTest = new IsExpression(
          new VariableGet(targetValue), rtiLibrary.markerClass.rawType);
      Expression tagCheck = new PropertyGet(new VariableGet(targetValue),
          builder.getTypeTestTagName(declaration));
      Expression check = new LogicalExpression(markerClassTest, "&&", tagCheck);
      if (checkArguments) {
        // TODO(karlklose): support a direct argument check, we already checked
        // the declaration.
        Expression uninterceptedCheck = new Let(
            typeExpression,
            builder.createIsSubtypeOf(
                new VariableGet(targetValue), new VariableGet(typeExpression),
                targetHasTypeProperty: true));
        check = new LogicalExpression(check, "&&", uninterceptedCheck);
      }
      return new Let(targetValue, check);
    } else {
      return builder.createIsSubtypeOf(target, createRuntimeType(type));
    }
  }

  Expression visitListLiteral(ListLiteral node) {
    trace(node);
    node.transformChildren(this);
    return builder.callAttachType(
        node,
        new InterfaceType(
            builder.coreTypes.listClass, <DartType>[node.typeArgument]));
  }

  Expression visitMapLiteral(MapLiteral node) {
    trace(node);
    node.transformChildren(this);
    return builder.callAttachType(
        node,
        new InterfaceType(builder.coreTypes.mapClass,
            <DartType>[node.keyType, node.valueType]));
  }
}
