// 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 '../../elements/resolution_types.dart' show ResolutionDartType;
import '../../deferred_load.dart' show OutputUnit;
import '../../elements/elements.dart' show ClassElement, FieldElement;
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 '../../universe/selector.dart' show Selector;
import '../../util/util.dart' show equalElements;
import '../../world.dart' show ClosedWorld;
import '../js_emitter.dart' hide Emitter, EmitterFactory;
import '../model.dart';
import 'emitter.dart';

class ClassEmitter extends CodeEmitterHelper {
  final ClosedWorld 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;

    assert(!(classElement is ClassElement && !classElement.isDeclaration),
        failedAt(classElement));

    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) {
    List<jsAst.Name> fieldNames = <jsAst.Name>[];

    if (!compiler.options.useContentSecurityPolicy) return;

    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.deferredLoadTask.outputUnitForEntity(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;
    }

    var fieldMetadata = <jsAst.Expression>[];
    bool hasMetadata = false;
    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) {
        dynamic metadata =
            task.metadataCollector.buildFieldMetadataFunction(fieldElement);
        if (metadata != null) {
          hasMetadata = true;
        } else {
          metadata = new jsAst.LiteralNull();
        }
        fieldMetadata.add(metadata);
        recordMangledField(fieldElement, accessorName,
            namer.privateName(fieldElement.memberName));
        List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
        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]));
        }
        // Fields can only be reflected if their declaring class is reflectable
        // (as they are only accessible via [ClassMirror.declarations]).
        // However, set/get operations can be performed on them, so they are
        // reflectable in some sense, which leads to [isAccessibleByReflection]
        // reporting `true`.
        if (backend.mirrorsData.isMemberAccessibleByReflection(fieldElement)) {
          fieldNameParts.add(new jsAst.LiteralString('-'));
          if (fieldElement.isTopLevel ||
              backend.mirrorsData
                  .isClassAccessibleByReflection(fieldElement.enclosingClass)) {
            // TODO(redemption): Support field entities.
            FieldElement element = fieldElement;
            ResolutionDartType type = element.type;
            fieldNameParts.add(task.metadataCollector.reifyType(type));
          }
        }
        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;
      }
    }

    if (hasMetadata) {
      builder.fieldMetadata = fieldMetadata;
    }
    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));
      generateReflectionDataForFieldGetterOrSetter(member, setterName, builder,
          isGetter: false);
    }
  }

  /// 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;
    assert(!(classElement is ClassElement && !classElement.isDeclaration),
        failedAt(classElement));

    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;

    var metadata =
        task.metadataCollector.buildClassMetadataFunction(classEntity);
    if (metadata != null) {
      classBuilder.addPropertyByName("@", metadata);
    }

    if (backend.mirrorsData.isClassAccessibleByReflection(classEntity)) {
      // TODO(redemption): Handle class entities.
      ClassElement classElement = classEntity;
      List<ResolutionDartType> typeVars = classElement.typeVariables;
      Iterable typeVariableProperties =
          emitter.typeVariableCodegenAnalysis.typeVariablesOf(classElement);

      ClassElement superclass = classElement.superclass;
      bool hasSuper = superclass != null;
      if ((!typeVariableProperties.isEmpty && !hasSuper) ||
          (hasSuper && !equalElements(superclass.typeVariables, typeVars))) {
        classBuilder.addPropertyByName(
            '<>', new jsAst.ArrayInitializer(typeVariableProperties.toList()));
      }
    }

    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) {
      if (!backend.mirrorsData.isClassAccessibleByReflection(classEntity) ||
          cls.onlyForRti) {
        // TODO(herhut): Fix use of reflection name here.
        enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0));
      } else {
        // TODO(redemption): Handle class entities.
        ClassElement classElement = classEntity;
        List<jsAst.Expression> types = <jsAst.Expression>[];
        if (classElement.supertype != null) {
          types.add(task.metadataCollector.reifyType(classElement.supertype));
        }
        for (ResolutionDartType interface in classElement.interfaces) {
          types.add(task.metadataCollector.reifyType(interface));
        }
        // TODO(herhut): Fix use of reflection name here.
        enclosingBuilder.addPropertyByName(
            "+$reflectionName", new jsAst.ArrayInitializer(types));
      }
    }
  }

  void recordMangledField(
      FieldEntity member, jsAst.Name accessorName, String memberName) {
    if (!backend.mirrorsData.shouldRetainGetter(member)) return;
    String previousName;
    if (member.isInstanceMember) {
      previousName = emitter.mangledFieldNames
          .putIfAbsent(namer.deriveGetterName(accessorName), () => memberName);
    } else {
      previousName = emitter.mangledGlobalFieldNames
          .putIfAbsent(accessorName, () => memberName);
    }
    assert(previousName == memberName,
        failedAt(member, '$previousName != ${memberName}'));
  }

  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.deferredLoadTask.outputUnitForEntity(member);
    emitter
        .cspPrecompiledFunctionFor(outputUnit)
        .add(js('#.prototype.# = #', [className, getterName, function]));
    if (backend.mirrorsData.isMemberAccessibleByReflection(member)) {
      emitter.cspPrecompiledFunctionFor(outputUnit).add(js(
          '#.prototype.#.${namer.reflectableField} = 1',
          [className, getterName]));
    }
  }

  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.deferredLoadTask.outputUnitForEntity(member);
    emitter
        .cspPrecompiledFunctionFor(outputUnit)
        .add(js('#.prototype.# = #', [className, setterName, function]));
    if (backend.mirrorsData.isMemberAccessibleByReflection(member)) {
      emitter.cspPrecompiledFunctionFor(outputUnit).add(js(
          '#.prototype.#.${namer.reflectableField} = 1',
          [className, setterName]));
    }
  }

  void generateReflectionDataForFieldGetterOrSetter(
      MemberEntity member, jsAst.Name name, ClassBuilder builder,
      {bool isGetter}) {
    Selector selector = isGetter
        ? new Selector.getter(member.memberName.getter)
        : new Selector.setter(member.memberName.setter);
    String reflectionName = emitter.getReflectionSelectorName(selector, name);
    if (reflectionName != null) {
      var reflectable = js(
          backend.mirrorsData.isMemberAccessibleByReflection(member)
              ? '1'
              : '0');
      builder.addPropertyByName('+$reflectionName', reflectable);
    }
  }
}
