// 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.

library dart2js.js_emitter.full_emitter.class_emitter;

import '../../common.dart';
import '../../common/names.dart' show Names;
import '../../common_elements.dart';
import '../../deferred_load.dart' show OutputUnit;
import '../../elements/entities.dart';
import '../../js/js.dart' as jsAst;
import '../../js/js.dart' show js;
import '../../js_backend/js_backend.dart' show CompoundName, Namer;
import '../../world.dart' show JClosedWorld;
import '../js_emitter.dart' hide Emitter, EmitterFactory;
import '../model.dart';
import 'emitter.dart';

class ClassEmitter extends CodeEmitterHelper {
  final JClosedWorld closedWorld;

  ClassEmitter(this.closedWorld);

  ClassStubGenerator get _stubGenerator => new ClassStubGenerator(task.emitter,
      closedWorld.commonElements, namer, codegenWorldBuilder, closedWorld,
      enableMinification: compiler.options.enableMinification);

  ElementEnvironment get _elementEnvironment => closedWorld.elementEnvironment;

  /**
   * Documentation wanted -- johnniwinther
   */
  void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
    ClassEntity classElement = cls.element;

    emitter.needsClassSupport = true;

    ClassEntity superclass = _elementEnvironment.getSuperClass(classElement);
    jsAst.Name superName;
    if (superclass != null) {
      superName = namer.className(superclass);
    }

    if (cls.isMixinApplication) {
      MixinApplication mixinApplication = cls;
      jsAst.Name mixinName = mixinApplication.mixinClass.name;
      superName = new CompoundName([superName, Namer.literalPlus, mixinName]);
      emitter.needsMixinSupport = true;
    }

    ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
    builder.superName = superName;
    emitConstructorsForCSP(cls);
    emitFields(cls, builder);
    if (cls.hasRtiField) {
      builder.addField(namer.rtiFieldJsName);
    }
    emitCheckedClassSetters(cls, builder);
    emitClassGettersSettersForCSP(cls, builder);
    emitInstanceMembers(cls, builder);
    emitStubs(cls.callStubs, builder);
    emitRuntimeTypeInformation(cls, builder);
    emitNativeInfo(cls, builder);

    if (classElement == closedWorld.commonElements.closureClass) {
      // We add a special getter here to allow for tearing off a closure from
      // itself.
      jsAst.Fun function = js('function() { return this; }');
      jsAst.Name name = namer.getterForMember(Names.call);
      builder.addProperty(name, function);
    }

    emitClassBuilderWithReflectionData(
        cls, builder, enclosingBuilder, fragment);
  }

  /**
  * Emits the precompiled constructor when in CSP mode.
  */
  void emitConstructorsForCSP(Class cls) {
    if (!compiler.options.useContentSecurityPolicy) return;

    List<jsAst.Name> fieldNames = <jsAst.Name>[];
    if (!cls.onlyForRti && !cls.isNative) {
      fieldNames = cls.fields.map((Field field) => field.name).toList();
    }

    ClassEntity classElement = cls.element;

    jsAst.Expression constructorAst = _stubGenerator.generateClassConstructor(
        classElement, fieldNames, cls.hasRtiField);

    jsAst.Name constructorName = namer.className(classElement);
    OutputUnit outputUnit =
        compiler.backend.outputUnitData.outputUnitForClass(classElement);
    emitter.assemblePrecompiledConstructor(
        outputUnit, constructorName, constructorAst, fieldNames);
  }

  /// Returns `true` if fields added.
  bool emitFields(FieldContainer container, ClassBuilder builder,
      {bool classIsNative: false, bool emitStatics: false}) {
    Iterable<Field> fields;
    if (container is Class) {
      if (emitStatics) {
        fields = container.staticFieldsForReflection;
      } else if (container.onlyForRti) {
        return false;
      } else {
        fields = container.fields;
      }
    } else {
      assert(container is Library);
      assert(emitStatics);
      fields = container.staticFieldsForReflection;
    }

    bool fieldsAdded = false;

    for (Field field in fields) {
      FieldEntity fieldElement = field.element;
      jsAst.Name name = field.name;
      jsAst.Name accessorName = field.accessorName;
      bool needsGetter = field.needsGetter;
      bool needsSetter = field.needsUncheckedSetter;

      // Ignore needsCheckedSetter - that is handled below.
      bool needsAccessor = (needsGetter || needsSetter);
      // We need to output the fields for non-native classes so we can auto-
      // generate the constructor.  For native classes there are no
      // constructors, so we don't need the fields unless we are generating
      // accessors at runtime.
      bool needsFieldsForConstructor = !emitStatics && !classIsNative;
      if (needsFieldsForConstructor || needsAccessor) {
        List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
        if (field.nullInitializerInAllocator) {
          fieldNameParts.add(js.stringPart('0'));
        }
        if (!needsAccessor) {
          // Emit field for constructor generation.
          assert(!classIsNative);
          fieldNameParts.add(name);
        } else {
          // Emit (possibly renaming) field name so we can add accessors at
          // runtime.
          if (name != accessorName) {
            fieldNameParts.add(accessorName);
            fieldNameParts.add(js.stringPart(':'));
          }
          fieldNameParts.add(name);
          if (field.needsInterceptedGetter) {
            emitter.interceptorEmitter.interceptorInvocationNames
                .add(namer.getterForElement(fieldElement));
          }
          // TODO(16168): The setter creator only looks at the getter-name.
          // Even though the setter could avoid the interceptor convention we
          // currently still need to add the additional argument.
          if (field.needsInterceptedGetter || field.needsInterceptedSetter) {
            emitter.interceptorEmitter.interceptorInvocationNames
                .add(namer.setterForMember(fieldElement));
          }

          int code = field.getterFlags + (field.setterFlags << 2);
          if (code == 0) {
            reporter.internalError(
                fieldElement, 'Field code is 0 ($fieldElement).');
          }
          fieldNameParts.add(
              js.stringPart(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]));
        }
        jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts);
        builder.addField(fieldNameAst);
        // Add 1 because adding a field to the class also requires a comma
        compiler.dumpInfoTask.registerEntityAst(fieldElement, fieldNameAst);
        fieldsAdded = true;
      }
    }

    return fieldsAdded;
  }

  /// Emits checked setters for fields.
  void emitCheckedClassSetters(Class cls, ClassBuilder builder) {
    if (cls.onlyForRti) return;

    for (StubMethod method in cls.checkedSetters) {
      MemberEntity member = method.element;
      assert(member != null);
      jsAst.Expression code = method.code;
      jsAst.Name setterName = method.name;
      compiler.dumpInfoTask
          .registerEntityAst(member, builder.addProperty(setterName, code));
    }
  }

  /// Emits getters/setters for fields if compiling in CSP mode.
  void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) {
    if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return;

    for (Field field in cls.fields) {
      FieldEntity member = field.element;
      reporter.withCurrentElement(member, () {
        if (field.needsGetter) {
          emitGetterForCSP(member, field.name, field.accessorName, builder);
        }
        if (field.needsUncheckedSetter) {
          emitSetterForCSP(member, field.name, field.accessorName, builder);
        }
      });
    }
  }

  void emitStubs(Iterable<StubMethod> stubs, ClassBuilder builder) {
    for (Method method in stubs) {
      jsAst.Property property = builder.addProperty(method.name, method.code);
      compiler.dumpInfoTask.registerEntityAst(method.element, property);
    }
  }

  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [classElement] must be a declaration element.
   */
  void emitInstanceMembers(Class cls, ClassBuilder builder) {
    ClassEntity classElement = cls.element;

    if (cls.onlyForRti || cls.isMixinApplication) return;

    // TODO(herhut): This is a no-op. Should it be removed?
    for (Field field in cls.fields) {
      emitter.containerBuilder.addMemberField(field, builder);
    }

    for (Method method in cls.methods) {
      assert(method.element.isInstanceMember, failedAt(classElement));
      emitter.containerBuilder.addMemberMethod(method, builder);
    }

    if (classElement == closedWorld.commonElements.objectClass &&
        closedWorld.backendUsage.isNoSuchMethodUsed) {
      // Emit the noSuchMethod handlers on the Object prototype now,
      // so that the code in the dynamicFunction helper can find
      // them. Note that this helper is invoked before analyzing the
      // full JS script.
      emitter.nsmEmitter.emitNoSuchMethodHandlers(builder.addProperty);
    }
  }

  /// Emits the members from the model.
  void emitRuntimeTypeInformation(Class cls, ClassBuilder builder) {
    assert(builder.functionType == null);
    if (cls.functionTypeIndex != null) {
      builder.functionType = cls.functionTypeIndex;
    }

    for (Method method in cls.isChecks) {
      builder.addProperty(method.name, method.code);
    }
  }

  void emitNativeInfo(Class cls, ClassBuilder builder) {
    jsAst.Expression nativeInfo = NativeGenerator.encodeNativeInfo(cls);
    if (nativeInfo != null) {
      builder.addPropertyByName(namer.nativeSpecProperty, nativeInfo);
    }
  }

  void emitClassBuilderWithReflectionData(Class cls, ClassBuilder classBuilder,
      ClassBuilder enclosingBuilder, Fragment fragment) {
    ClassEntity classEntity = cls.element;
    jsAst.Name className = cls.name;

    List<jsAst.Property> statics = new List<jsAst.Property>();
    ClassBuilder staticsBuilder =
        new ClassBuilder.forStatics(classEntity, namer);
    if (emitFields(cls, staticsBuilder, emitStatics: true)) {
      jsAst.ObjectInitializer initializer =
          staticsBuilder.toObjectInitializer();
      compiler.dumpInfoTask.registerEntityAst(classEntity, initializer);
      jsAst.Node property = initializer.properties.single;
      compiler.dumpInfoTask.registerEntityAst(classEntity, property);
      statics.add(property);
    }

    // TODO(herhut): Do not grab statics out of the properties.
    ClassBuilder classProperties =
        emitter.classDescriptors[fragment]?.remove(classEntity);
    if (classProperties != null) {
      statics.addAll(classProperties.properties);
    }

    if (!statics.isEmpty) {
      classBuilder.addProperty(
          namer.staticsPropertyName, // 'static' or its minified name.
          new jsAst.ObjectInitializer(statics, isOneLiner: false));
    }

    // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
    jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer();
    compiler.dumpInfoTask
        .registerEntityAst(classBuilder.element, propertyValue);
    enclosingBuilder.addProperty(className, propertyValue);

    String reflectionName =
        emitter.getReflectionClassName(classEntity, className);
    if (reflectionName != null) {
      // TODO(herhut): Fix use of reflection name here.
      enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0));
    }
  }

  void emitGetterForCSP(FieldEntity member, jsAst.Name fieldName,
      jsAst.Name accessorName, ClassBuilder builder) {
    jsAst.Expression function =
        _stubGenerator.generateGetter(member, fieldName);

    jsAst.Name getterName = namer.deriveGetterName(accessorName);
    ClassEntity cls = member.enclosingClass;
    jsAst.Name className = namer.className(cls);
    OutputUnit outputUnit =
        compiler.backend.outputUnitData.outputUnitForMember(member);
    emitter
        .cspPrecompiledFunctionFor(outputUnit)
        .add(js('#.prototype.# = #', [className, getterName, function]));
  }

  void emitSetterForCSP(FieldEntity member, jsAst.Name fieldName,
      jsAst.Name accessorName, ClassBuilder builder) {
    jsAst.Expression function =
        _stubGenerator.generateSetter(member, fieldName);

    jsAst.Name setterName = namer.deriveSetterName(accessorName);
    ClassEntity cls = member.enclosingClass;
    jsAst.Name className = namer.className(cls);
    OutputUnit outputUnit =
        compiler.backend.outputUnitData.outputUnitForMember(member);
    emitter
        .cspPrecompiledFunctionFor(outputUnit)
        .add(js('#.prototype.# = #', [className, setterName, function]));
  }
}
