// 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 dart2js.js_emitter.lazy_emitter;

import 'package:js_runtime/shared/embedded_names.dart'
    show JsBuiltin, METADATA, TYPES;

import '../../common.dart';
import '../../compiler.dart' show Compiler;
import '../../constants/values.dart' show ConstantValue;
import '../../elements/elements.dart'
    show ClassElement, Element, FieldElement, FunctionElement;
import '../../js/js.dart' as js;
import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;

import '../js_emitter.dart' show NativeEmitter;
import '../js_emitter.dart' as emitterTask show Emitter;
import '../model.dart';
import '../program_builder/program_builder.dart' show ProgramBuilder;

import 'model_emitter.dart';

class Emitter implements emitterTask.Emitter {
  final Compiler _compiler;
  final Namer namer;
  final ModelEmitter _emitter;

  JavaScriptBackend get _backend => _compiler.backend;

  Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter)
      : this._compiler = compiler,
        this.namer = namer,
        _emitter = new ModelEmitter(compiler, namer, nativeEmitter);

  DiagnosticReporter get reporter => _compiler.reporter;

  @override
  String get patchVersion => "lazy";

  @override
  int emitProgram(ProgramBuilder programBuilder) {
    Program program = programBuilder.buildProgram();
    return _emitter.emitProgram(program);
  }

  @override
  bool get supportsReflection => false;

  // TODO(floitsch): copied from full emitter. Adjust or share.
  @override
  bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
    return _emitter.isConstantInlinedOrAlreadyEmitted(constant);
  }

  // TODO(floitsch): copied from full emitter. Adjust or share.
  @override
  int compareConstants(ConstantValue a, ConstantValue b) {
    return _emitter.compareConstants(a, b);
  }

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

  @override
  js.Expression generateEmbeddedGlobalAccess(String global) {
    return _emitter.generateEmbeddedGlobalAccess(global);
  }

  @override
  // TODO(herhut): Use a single shared function.
  js.Expression generateFunctionThatReturnsNull() {
    return js.js('function() {}');
  }

  js.PropertyAccess _globalPropertyAccess(Element element) {
    js.Name name = namer.globalPropertyName(element);
    js.PropertyAccess pa = new js.PropertyAccess(
        new js.VariableUse(namer.globalObjectFor(element)), name);
    return pa;
  }

  @override
  js.Expression isolateLazyInitializerAccess(FieldElement element) {
    return js.js('#.#',
        [namer.globalObjectFor(element), namer.lazyInitializerName(element)]);
  }

  @override
  js.Expression isolateStaticClosureAccess(FunctionElement element) {
    return _emitter.generateStaticClosureAccess(element);
  }

  @override
  js.PropertyAccess staticFieldAccess(FieldElement element) {
    return _globalPropertyAccess(element);
  }

  @override
  js.PropertyAccess staticFunctionAccess(FunctionElement element) {
    return _globalPropertyAccess(element);
  }

  @override
  js.PropertyAccess constructorAccess(ClassElement element) {
    return _globalPropertyAccess(element);
  }

  @override
  js.PropertyAccess prototypeAccess(
      ClassElement element, bool hasBeenInstantiated) {
    js.Expression constructor =
        hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
    return js.js('#.prototype', constructor);
  }

  @override
  js.Expression interceptorClassAccess(ClassElement element) {
    // Some interceptors are eagerly constructed. However, native interceptors
    // aren't.
    return js.js('#.ensureResolved()', _globalPropertyAccess(element));
  }

  @override
  js.Expression typeAccess(Element element) {
    // TODO(floitsch): minify 'ensureResolved'.
    // TODO(floitsch): don't emit `ensureResolved` for eager classes.
    return js.js('#.ensureResolved()', _globalPropertyAccess(element));
  }

  @override
  js.Template templateForBuiltin(JsBuiltin builtin) {
    String typeNameProperty = ModelEmitter.typeNameProperty;

    switch (builtin) {
      case JsBuiltin.dartObjectConstructor:
        return js.js.expressionTemplateYielding(
            typeAccess(_compiler.coreClasses.objectClass));

      case JsBuiltin.isCheckPropertyToJsConstructorName:
        int isPrefixLength = namer.operatorIsPrefix.length;
        return js.js.expressionTemplateFor('#.substring($isPrefixLength)');

      case JsBuiltin.isFunctionType:
        return _backend.rtiEncoder.templateForIsFunctionType;

      case JsBuiltin.rawRtiToJsConstructorName:
        return js.js.expressionTemplateFor("#.$typeNameProperty");

      case JsBuiltin.rawRuntimeType:
        return js.js.expressionTemplateFor("#.constructor");

      case JsBuiltin.createFunctionTypeRti:
        return _backend.rtiEncoder.templateForCreateFunctionType;

      case JsBuiltin.isSubtype:
        // TODO(floitsch): move this closer to where is-check properties are
        // built.
        String isPrefix = namer.operatorIsPrefix;
        return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");

      case JsBuiltin.isGivenTypeRti:
        return js.js.expressionTemplateFor('#.$typeNameProperty === #');

      case JsBuiltin.getMetadata:
        return _emitter.templateForReadMetadata;

      case JsBuiltin.getType:
        return _emitter.templateForReadType;

      case JsBuiltin.createDartClosureFromNameOfStaticFunction:
        throw new UnsupportedError('createDartClosureFromNameOfStaticFunction');

      default:
        reporter.internalError(
            NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
        return null;
    }
  }

  @override
  void invalidateCaches() {}
}
