// 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/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_);
  }
}
