// Copyright (c) 2014, 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 code_generator_dependencies;

import '../backend_helpers.dart' show
    BackendHelpers;
import '../js_backend.dart';

import '../../common.dart';
import '../../common/registry.dart' show
    Registry;
import '../../common/codegen.dart' show
    CodegenRegistry;
import '../../compiler.dart' show
    Compiler;
import '../../constants/values.dart';
import '../../dart_types.dart' show
    DartType,
    TypeVariableType,
    InterfaceType;
import '../../enqueue.dart' show
    CodegenEnqueuer;
import '../../elements/elements.dart';
import '../../js_emitter/js_emitter.dart';
import '../../js/js.dart' as js;
import '../../native/native.dart' show NativeBehavior;
import '../../universe/selector.dart' show
    Selector;
import '../../world.dart' show
    ClassWorld;
import '../../types/types.dart';

/// Encapsulates the dependencies of the function-compiler to the compiler,
/// backend and emitter.
// TODO(sigurdm): Should be refactored when we have a better feeling for the
// interface.
class Glue {
  final Compiler _compiler;

  CodegenEnqueuer get _enqueuer => _compiler.enqueuer.codegen;

  FunctionElement get getInterceptorMethod => _helpers.getInterceptorMethod;

  JavaScriptBackend get _backend => _compiler.backend;

  BackendHelpers get _helpers => _backend.helpers;

  CodeEmitterTask get _emitter => _backend.emitter;

  Namer get _namer => _backend.namer;

  Glue(this._compiler);

  ClassWorld get classWorld => _compiler.world;

  DiagnosticReporter get reporter => _compiler.reporter;

  js.Expression constantReference(ConstantValue value) {
    return _emitter.constantReference(value);
  }

  reportInternalError(String message) {
    reporter.internalError(CURRENT_ELEMENT_SPANNABLE, message);
  }

  bool isUsedAsMixin(ClassElement classElement) {
    return classWorld.isUsedAsMixin(classElement);
  }

  js.Expression staticFunctionAccess(FunctionElement element) {
    return _backend.emitter.staticFunctionAccess(element);
  }

  js.Expression isolateStaticClosureAccess(FunctionElement element) {
    return _backend.emitter.isolateStaticClosureAccess(element);
  }

  js.Expression staticFieldAccess(FieldElement element) {
    return _backend.emitter.staticFieldAccess(element);
  }

  js.Expression isolateLazyInitializerAccess(FieldElement element) {
    return _backend.emitter.isolateLazyInitializerAccess(element);
  }

  bool isLazilyInitialized(FieldElement element) {
    return _backend.constants.lazyStatics.contains(element);
  }

  String safeVariableName(String name) {
    return _namer.safeVariableName(name);
  }

  ClassElement get listClass => _compiler.coreClasses.listClass;

  ConstructorElement get mapLiteralConstructor {
    return _helpers.mapLiteralConstructor;
  }

  ConstructorElement get mapLiteralConstructorEmpty {
    return _helpers.mapLiteralConstructorEmpty;
  }

  FunctionElement get identicalFunction => _compiler.identicalFunction;

  js.Name invocationName(Selector selector) {
    return _namer.invocationName(selector);
  }

  FunctionElement get createInvocationMirrorMethod {
    return _helpers.createInvocationMirror;
  }

  bool isInterceptedSelector(Selector selector) {
    return _backend.isInterceptedSelector(selector);
  }

  bool isInterceptedMethod(Element element) {
    return _backend.isInterceptedMethod(element);
  }

  bool isInterceptorClass(ClassElement element) {
    return element.isSubclassOf(_helpers.jsInterceptorClass);
  }

  Set<ClassElement> getInterceptedClassesOn(Selector selector) {
    return _backend.getInterceptedClassesOn(selector.name);
  }

  Set<ClassElement> get interceptedClasses {
    return _backend.interceptedClasses;
  }

  void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
    _backend.registerSpecializedGetInterceptor(classes);
  }

  js.Expression constructorAccess(ClassElement element) {
    return _backend.emitter.constructorAccess(element);
  }

  js.Name instanceFieldPropertyName(Element field) {
    return _namer.instanceFieldPropertyName(field);
  }

  js.Name instanceMethodName(FunctionElement element) {
    return _namer.instanceMethodName(element);
  }

  js.Expression prototypeAccess(ClassElement e,
                                {bool hasBeenInstantiated: false}) {
    return _emitter.prototypeAccess(e,
        hasBeenInstantiated: hasBeenInstantiated);
  }

  js.Name getInterceptorName(Set<ClassElement> interceptedClasses) {
    return _backend.namer.nameForGetInterceptor(interceptedClasses);
  }

  js.Expression getInterceptorLibrary() {
    return new js.VariableUse(
        _backend.namer.globalObjectFor(_helpers.interceptorsLibrary));
  }

  FunctionElement getWrapExceptionHelper() {
    return _helpers.wrapExceptionHelper;
  }

  FunctionElement getExceptionUnwrapper() {
    return _helpers.exceptionUnwrapper;
  }

  FunctionElement getTraceFromException() {
    return _helpers.traceFromException;
  }

  FunctionElement getCreateRuntimeType() {
    return _helpers.createRuntimeType;
  }

  FunctionElement getRuntimeTypeToString() {
    return _helpers.runtimeTypeToString;
  }

  FunctionElement getRuntimeTypeArgument() {
    return _helpers.getRuntimeTypeArgument;
  }

  FunctionElement getTypeArgumentByIndex() {
    return _helpers.getTypeArgumentByIndex;
  }

  FunctionElement getAddRuntimeTypeInformation() {
    return _helpers.setRuntimeTypeInfo;
  }

  /// checkSubtype(value, $isT, typeArgs, $asT)
  FunctionElement getCheckSubtype() {
    return _helpers.checkSubtype;
  }

  /// subtypeCast(value, $isT, typeArgs, $asT)
  FunctionElement getSubtypeCast() {
    return _helpers.subtypeCast;
  }

  /// checkSubtypeOfRuntime(value, runtimeType)
  FunctionElement getCheckSubtypeOfRuntimeType() {
    return _helpers.checkSubtypeOfRuntimeType;
  }

  /// subtypeOfRuntimeTypeCast(value, runtimeType)
  FunctionElement getSubtypeOfRuntimeTypeCast() {
    return _helpers.subtypeOfRuntimeTypeCast;
  }

  js.Expression getRuntimeTypeName(ClassElement cls) {
    return js.quoteName(_namer.runtimeTypeName(cls));
  }

  int getTypeVariableIndex(TypeVariableType variable) {
    return variable.element.index;
  }

  bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
    ClassWorld classWorld = _compiler.world;
    if (classWorld.isUsedAsMixin(cls)) return true;

    return _compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
      return !_backend.rti.isTrivialSubstitution(subclass, cls);
    });
  }

  js.Expression generateTypeRepresentation(DartType dartType,
                                           List<js.Expression> arguments,
                                           CodegenRegistry registry) {
    int variableIndex = 0;
    js.Expression representation = _backend.rtiEncoder.getTypeRepresentation(
        dartType,
        (_) => arguments[variableIndex++]);
    assert(variableIndex == arguments.length);
    // Representation contains JavaScript Arrays.
    registry.registerInstantiatedClass(_helpers.jsArrayClass);
    return representation;
  }

  js.Name getTypeTestTag(DartType type) {
    return _backend.namer.operatorIsType(type);
  }

  js.Name getTypeSubstitutionTag(ClassElement element) {
    return _backend.namer.substitutionName(element);
  }

  bool operatorEqHandlesNullArgument(FunctionElement element) {
    return _backend.operatorEqHandlesNullArgument(element);
  }

  bool hasStrictSubtype(ClassElement element) {
    return _compiler.world.hasAnyStrictSubtype(element);
  }

  ClassElement get jsFixedArrayClass => _helpers.jsFixedArrayClass;
  ClassElement get jsExtendableArrayClass => _helpers.jsExtendableArrayClass;
  ClassElement get jsUnmodifiableArrayClass =>
      _helpers.jsUnmodifiableArrayClass;
  ClassElement get jsMutableArrayClass => _helpers.jsMutableArrayClass;

  bool isStringClass(ClassElement classElement) =>
      classElement == _helpers.jsStringClass ||
      classElement == _compiler.coreClasses.stringClass;

  bool isBoolClass(ClassElement classElement) =>
      classElement == _helpers.jsBoolClass ||
      classElement == _compiler.coreClasses.boolClass;

  // TODO(sra,johnniwinther): Should this be part of CodegenRegistry?
  void registerNativeBehavior(NativeBehavior nativeBehavior, node) {
    if (nativeBehavior == null) return;
    _enqueuer.nativeEnqueuer.registerNativeBehavior(nativeBehavior, node);
  }

  ConstantValue getDefaultParameterValue(ParameterElement elem) {
    return _backend.constants.getConstantValueForVariable(elem);
  }

  TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
    return _compiler.world.extendMaskIfReachesAll(selector, mask);
  }

  FunctionElement get closureFromTearOff => _backend.helpers.closureFromTearOff;

  js.Name registerOneShotInterceptor(Selector selector) {
    return _backend.registerOneShotInterceptor(selector);
  }

  bool mayGenerateInstanceofCheck(DartType type) {
    return _backend.mayGenerateInstanceofCheck(type);
  }

  bool methodUsesReceiverArgument(FunctionElement function) {
    assert(isInterceptedMethod(function));
    ClassElement class_ = function.enclosingClass.declaration;
    return isInterceptorClass(class_) || isUsedAsMixin(class_);
  }
}
