// Copyright (c) 2013, 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 '../common.dart';
import '../common/registry.dart' show Registry;
import '../compiler.dart' show Compiler;
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../enqueue.dart' show Enqueuer;
import '../js/js.dart' as jsAst;
import '../js_emitter/js_emitter.dart'
    show CodeEmitterTask, MetadataCollector, Placeholder;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/use.dart' show StaticUse;
import '../universe/world_impact.dart';
import '../util/util.dart';
import 'backend.dart';

/**
 * Handles construction of TypeVariable constants needed at runtime.
 */
class TypeVariableHandler {
  final Compiler _compiler;
  ConstructorElement _typeVariableConstructor;

  /**
   * Set to 'true' on first encounter of a class with type variables.
   */
  bool _seenClassesWithTypeVariables = false;

  /**
   *  Maps a class element to a list with indices that point to type variables
   *  constants for each of the class' type variables.
   */
  Map<ClassElement, List<jsAst.Expression>> _typeVariables =
      new Map<ClassElement, List<jsAst.Expression>>();

  /**
   *  Maps a TypeVariableType to the index pointing to the constant representing
   *  the corresponding type variable at runtime.
   */
  Map<TypeVariableElement, jsAst.Expression> _typeVariableConstants =
      new Map<TypeVariableElement, jsAst.Expression>();

  /// Impact builder used for the codegen world computation.
  // TODO(johnniwinther): Add impact builder for resolution.
  final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();

  TypeVariableHandler(this._compiler);

  ClassElement get _typeVariableClass => _backend.helpers.typeVariableClass;
  CodeEmitterTask get _task => _backend.emitter;
  MetadataCollector get _metadataCollector => _task.metadataCollector;
  JavaScriptBackend get _backend => _compiler.backend;
  DiagnosticReporter get reporter => _compiler.reporter;

  void onQueueEmpty(Enqueuer enqueuer) {
    if (enqueuer.isResolutionQueue) return;

    enqueuer.applyImpact(null, impactBuilder.flush());
  }

  void registerClassWithTypeVariables(
      ClassElement cls, Enqueuer enqueuer, Registry registry) {
    if (enqueuer.isResolutionQueue) {
      // On first encounter, we have to ensure that the support classes get
      // resolved.
      if (!_seenClassesWithTypeVariables) {
        _backend.enqueueClass(enqueuer, _typeVariableClass, registry);
        _typeVariableClass.ensureResolved(_compiler.resolution);
        Link constructors = _typeVariableClass.constructors;
        if (constructors.isEmpty && constructors.tail.isEmpty) {
          reporter.internalError(_typeVariableClass,
              "Class '$_typeVariableClass' should only have one constructor");
        }
        _typeVariableConstructor = _typeVariableClass.constructors.head;
        _backend.enqueueInResolution(_typeVariableConstructor, registry);
        _backend.registerInstantiatedType(
            _typeVariableClass.rawType, enqueuer, registry);
        enqueuer.registerStaticUse(new StaticUse.staticInvoke(
            _backend.registerBackendUse(_backend.helpers.createRuntimeType),
            CallStructure.ONE_ARG));
        _seenClassesWithTypeVariables = true;
      }
    } else {
      if (_backend.isAccessibleByReflection(cls)) {
        processTypeVariablesOf(cls);
      }
    }
  }

  void processTypeVariablesOf(ClassElement cls) {
    // Do not process classes twice.
    if (_typeVariables.containsKey(cls)) return;

    InterfaceType typeVariableType = _typeVariableClass.thisType;
    List<jsAst.Expression> constants = <jsAst.Expression>[];

    for (TypeVariableType currentTypeVariable in cls.typeVariables) {
      TypeVariableElement typeVariableElement = currentTypeVariable.element;

      jsAst.Expression boundIndex =
          _metadataCollector.reifyType(typeVariableElement.bound);
      ConstantValue boundValue = new SyntheticConstantValue(
          SyntheticConstantKind.TYPEVARIABLE_REFERENCE, boundIndex);
      ConstantExpression boundExpression =
          new SyntheticConstantExpression(boundValue);
      ConstantExpression constant = new ConstructedConstantExpression(
          _typeVariableConstructor.enclosingClass.thisType,
          _typeVariableConstructor,
          const CallStructure.unnamed(3), [
        new TypeConstantExpression(cls.rawType),
        new StringConstantExpression(currentTypeVariable.name),
        new SyntheticConstantExpression(boundValue)
      ]);

      _backend.constants.evaluate(constant);
      ConstantValue value = _backend.constants.getConstantValue(constant);
      _backend.computeImpactForCompileTimeConstant(value, impactBuilder, false);
      _backend.addCompileTimeConstantForEmission(value);
      constants
          .add(_reifyTypeVariableConstant(value, currentTypeVariable.element));
    }
    _typeVariables[cls] = constants;
  }

  /**
   * Adds [c] to [emitter.metadataCollector] and returns the index pointing to
   * the entry.
   *
   * If the corresponding type variable has already been encountered an
   * entry in the list has already been reserved and the constant is added
   * there, otherwise a new entry for [c] is created.
   */
  jsAst.Expression _reifyTypeVariableConstant(
      ConstantValue c, TypeVariableElement variable) {
    jsAst.Expression name = _task.constantReference(c);
    jsAst.Expression result = _metadataCollector.reifyExpression(name);
    if (_typeVariableConstants.containsKey(variable)) {
      Placeholder placeholder = _typeVariableConstants[variable];
      placeholder.bind(result);
    }
    _typeVariableConstants[variable] = result;
    return result;
  }

  /**
   * Returns the index pointing to the constant in [emitter.metadataCollector]
   * representing this type variable.
   *
   * If the constant has not yet been constructed, an entry is  allocated in
   * the global metadata list and the index pointing to this entry is returned.
   * When the corresponding constant is constructed later,
   * [reifyTypeVariableConstant] will be called and the constant will be added
   * on the allocated entry.
   */
  jsAst.Expression reifyTypeVariable(TypeVariableElement variable) {
    if (_typeVariableConstants.containsKey(variable)) {
      return _typeVariableConstants[variable];
    }

    Placeholder placeholder =
        _metadataCollector.getMetadataPlaceholder(variable);
    return _typeVariableConstants[variable] = placeholder;
  }

  List<jsAst.Expression> typeVariablesOf(ClassElement classElement) {
    List<jsAst.Expression> result = _typeVariables[classElement];
    if (result == null) {
      result = const <jsAst.Expression>[];
    }
    return result;
  }
}
