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

part of dart2js.js_emitter;

class ClassEmitter extends CodeEmitterHelper {
  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [classElement] must be a declaration element.
   */
  void generateClass(ClassElement classElement,
                     ClassBuilder properties,
                     Map<String, jsAst.Expression> additionalProperties) {
    final onlyForRti =
        task.typeTestEmitter.rtiNeededClasses.contains(classElement);

    assert(invariant(classElement, classElement.isDeclaration));
    assert(invariant(classElement, !classElement.isNative() || onlyForRti));

    task.needsDefineClass = true;
    String className = namer.getNameOfClass(classElement);

    ClassElement superclass = classElement.superclass;
    String superName = "";
    if (superclass != null) {
      superName = namer.getNameOfClass(superclass);
    }
    String runtimeName =
        namer.getPrimitiveInterceptorRuntimeName(classElement);

    if (classElement.isMixinApplication) {
      String mixinName = namer.getNameOfClass(computeMixinClass(classElement));
      superName = '$superName+$mixinName';
      task.needsMixinSupport = true;
    }

    ClassBuilder builder = new ClassBuilder();
    emitClassConstructor(classElement, builder, runtimeName,
                         onlyForRti: onlyForRti);
    emitFields(classElement, builder, superName, onlyForRti: onlyForRti);
    emitClassGettersSetters(classElement, builder, onlyForRti: onlyForRti);
    emitInstanceMembers(classElement, builder, onlyForRti: onlyForRti);
    task.typeTestEmitter.emitIsTests(classElement, builder);
    if (additionalProperties != null) {
      additionalProperties.forEach(builder.addProperty);
    }

    emitClassBuilderWithReflectionData(
        className, classElement, builder, properties);
  }

  void emitClassConstructor(ClassElement classElement,
                            ClassBuilder builder,
                            String runtimeName,
                            {bool onlyForRti: false}) {
    List<String> fields = <String>[];
    if (!onlyForRti && !classElement.isNative()) {
      visitFields(classElement, false,
                  (Element member,
                   String name,
                   String accessorName,
                   bool needsGetter,
                   bool needsSetter,
                   bool needsCheckedSetter) {
        fields.add(name);
      });
    }
    String constructorName = namer.getNameOfClass(classElement);
    task.precompiledFunction.add(new jsAst.FunctionDeclaration(
        new jsAst.VariableDeclaration(constructorName),
        js.fun(fields, fields.map(
            (name) => js('this.$name = $name')).toList())));
    if (runtimeName == null) {
      runtimeName = constructorName;
    }
    task.precompiledFunction.addAll([
        js('$constructorName.builtin\$cls = "$runtimeName"'),
        js.if_('!"name" in $constructorName',
              js('$constructorName.name = "$constructorName"')),
        js('\$desc=\$collectedClasses.$constructorName'),
        js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
        js('$constructorName.prototype = \$desc'),
    ]);

    task.precompiledConstructorNames.add(js(constructorName));
  }

  /// Returns `true` if fields added.
  bool emitFields(Element element,
                  ClassBuilder builder,
                  String superName,
                  { bool classIsNative: false,
                    bool emitStatics: false,
                    bool onlyForRti: false }) {
    assert(!emitStatics || !onlyForRti);
    bool isClass = false;
    bool isLibrary = false;
    if (element.isClass()) {
      isClass = true;
    } else if (element.isLibrary()) {
      isLibrary = false;
      assert(invariant(element, emitStatics));
    } else {
      throw new SpannableAssertionFailure(
          element, 'Must be a ClassElement or a LibraryElement');
    }
    StringBuffer buffer = new StringBuffer();
    if (emitStatics) {
      assert(invariant(element, superName == null, message: superName));
    } else {
      assert(invariant(element, superName != null));
      String nativeName =
          namer.getPrimitiveInterceptorRuntimeName(element);
      if (nativeName != null) {
        buffer.write('$nativeName/');
      }
      buffer.write('$superName;');
    }
    int bufferClassLength = buffer.length;

    String separator = '';

    var fieldMetadata = [];
    bool hasMetadata = false;

    if (!onlyForRti) {
      visitFields(element, emitStatics,
                  (VariableElement field,
                   String name,
                   String accessorName,
                   bool needsGetter,
                   bool needsSetter,
                   bool needsCheckedSetter) {
        // 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.
        if (!classIsNative || needsAccessor) {
          buffer.write(separator);
          separator = ',';
          var metadata = task.metadataEmitter.buildMetadataFunction(field);
          if (metadata != null) {
            hasMetadata = true;
          } else {
            metadata = new jsAst.LiteralNull();
          }
          fieldMetadata.add(metadata);
          recordMangledField(field, accessorName, field.name);
          if (!needsAccessor) {
            // Emit field for constructor generation.
            assert(!classIsNative);
            buffer.write(name);
          } else {
            // Emit (possibly renaming) field name so we can add accessors at
            // runtime.
            buffer.write(accessorName);
            if (name != accessorName) {
              buffer.write(':$name');
            }

            int getterCode = 0;
            if (needsGetter) {
              if (field.isInstanceMember()) {
                // 01:  function() { return this.field; }
                // 10:  function(receiver) { return receiver.field; }
                // 11:  function(receiver) { return this.field; }
                bool isIntercepted = backend.fieldHasInterceptedGetter(field);
                getterCode += isIntercepted ? 2 : 0;
                getterCode += backend.isInterceptorClass(element) ? 0 : 1;
                // TODO(sra): 'isInterceptorClass' might not be the correct test
                // for methods forced to use the interceptor convention because
                // the method's class was elsewhere mixed-in to an interceptor.
                assert(!field.isInstanceMember() || getterCode != 0);
                if (isIntercepted) {
                  task.interceptorEmitter.interceptorInvocationNames.add(
                      namer.getterName(field));
                }
              } else {
                getterCode = 1;
              }
            }
            int setterCode = 0;
            if (needsSetter) {
              if (field.isInstanceMember()) {
                // 01:  function(value) { this.field = value; }
                // 10:  function(receiver, value) { receiver.field = value; }
                // 11:  function(receiver, value) { this.field = value; }
                bool isIntercepted = backend.fieldHasInterceptedSetter(field);
                setterCode += isIntercepted ? 2 : 0;
                setterCode += backend.isInterceptorClass(element) ? 0 : 1;
                assert(!field.isInstanceMember() || setterCode != 0);
                if (isIntercepted) {
                  task.interceptorEmitter.interceptorInvocationNames.add(
                      namer.setterName(field));
                }
              } else {
                setterCode = 1;
              }
            }
            int code = getterCode + (setterCode << 2);
            if (code == 0) {
              compiler.reportInternalError(
                  field, 'Internal error: code is 0 ($element/$field)');
            } else {
              buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]);
            }
          }
          if (backend.isAccessibleByReflection(field)) {
            buffer.write('-');
            if (backend.isNeededForReflection(field)) {
              DartType type = field.computeType(compiler);
              buffer.write('${task.metadataEmitter.reifyType(type)}');
            }
          }
        }
      });
    }

    bool fieldsAdded = buffer.length > bufferClassLength;
    String compactClassData = buffer.toString();
    jsAst.Expression classDataNode = js.string(compactClassData);
    if (hasMetadata) {
      fieldMetadata.insert(0, classDataNode);
      classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata);
    }
    builder.addProperty('', classDataNode);
    return fieldsAdded;
  }

  void emitClassGettersSetters(ClassElement classElement,
                               ClassBuilder builder,
                               {bool onlyForRti: false}) {
    if (onlyForRti) return;

    visitFields(classElement, false,
                (VariableElement member,
                 String name,
                 String accessorName,
                 bool needsGetter,
                 bool needsSetter,
                 bool needsCheckedSetter) {
      compiler.withCurrentElement(member, () {
        if (needsCheckedSetter) {
          assert(!needsSetter);
          generateCheckedSetter(member, name, accessorName, builder);
        }
        if (needsGetter) {
          generateGetter(member, name, accessorName, builder);
        }
        if (needsSetter) {
          generateSetter(member, name, accessorName, builder);
        }
      });
    });
  }

  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [classElement] must be a declaration element.
   */
  void emitInstanceMembers(ClassElement classElement,
                           ClassBuilder builder,
                           {bool onlyForRti: false}) {
    assert(invariant(classElement, classElement.isDeclaration));

    if (onlyForRti || classElement.isMixinApplication) return;

    void visitMember(ClassElement enclosing, Element member) {
      assert(invariant(classElement, member.isDeclaration));
      if (member.isInstanceMember()) {
        task.containerBuilder.addMember(member, builder);
      }
    }

    classElement.implementation.forEachMember(
        visitMember,
        includeBackendMembers: true);

    if (identical(classElement, compiler.objectClass)
        && compiler.enabledNoSuchMethod) {
      // 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.
      if (!task.nativeEmitter.handleNoSuchMethod) {
        task.nsmEmitter.emitNoSuchMethodHandlers(builder.addProperty);
      }
    }
  }

  void emitClassBuilderWithReflectionData(String className,
                                          ClassElement classElement,
                                          ClassBuilder classBuilder,
                                          ClassBuilder enclosingBuilder) {
    var metadata = task.metadataEmitter.buildMetadataFunction(classElement);
    if (metadata != null) {
      classBuilder.addProperty("@", metadata);
    }

    if (backend.isNeededForReflection(classElement)) {
      Link typeVars = classElement.typeVariables;
      Iterable typeVariableProperties = task.typeVariableHandler
          .typeVariablesOf(classElement).map(js.toExpression);

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

    List<jsAst.Property> statics = new List<jsAst.Property>();
    ClassBuilder staticsBuilder = new ClassBuilder();
    if (emitFields(classElement, staticsBuilder, null, emitStatics: true)) {
      statics.add(staticsBuilder.properties.single);
    }

    Map<String, ClassBuilder> classPropertyLists =
        task.elementDecriptors.remove(classElement);
    if (classPropertyLists != null) {
      for (ClassBuilder classProperties in classPropertyLists.values) {
        // TODO(ahe): What about deferred?
        if (classProperties != null) {
          statics.addAll(classProperties.properties);
        }
      }
    }

    if (!statics.isEmpty) {
      classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics));
    }

    // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
    enclosingBuilder.addProperty(className, classBuilder.toObjectInitializer());

    String reflectionName = task.getReflectionName(classElement, className);
    if (reflectionName != null) {
      if (!backend.isNeededForReflection(classElement)) {
        enclosingBuilder.addProperty("+$reflectionName", js.number(0));
      } else {
        List<int> types = new List<int>();
        if (classElement.supertype != null) {
          types.add(task.metadataEmitter.reifyType(classElement.supertype));
        }
        for (DartType interface in classElement.interfaces) {
          types.add(task.metadataEmitter.reifyType(interface));
        }
        enclosingBuilder.addProperty("+$reflectionName",
            new jsAst.ArrayInitializer.from(types.map((typeNumber) =>
                js.number(typeNumber))));
      }
    }
  }

  /**
   * Calls [addField] for each of the fields of [element].
   *
   * [element] must be a [ClassElement] or a [LibraryElement].
   *
   * If [element] is a [ClassElement], the static fields of the class are
   * visited if [visitStatics] is true and the instance fields are visited if
   * [visitStatics] is false.
   *
   * If [element] is a [LibraryElement], [visitStatics] must be true.
   *
   * When visiting the instance fields of a class, the fields of its superclass
   * are also visited if the class is instantiated.
   *
   * Invariant: [element] must be a declaration element.
   */
  void visitFields(Element element, bool visitStatics, AcceptField f) {
    assert(invariant(element, element.isDeclaration));

    bool isClass = false;
    bool isLibrary = false;
    if (element.isClass()) {
      isClass = true;
    } else if (element.isLibrary()) {
      isLibrary = true;
      assert(invariant(element, visitStatics));
    } else {
      throw new SpannableAssertionFailure(
          element, 'Expected a ClassElement or a LibraryElement.');
    }

    // If the class is never instantiated we still need to set it up for
    // inheritance purposes, but we can simplify its JavaScript constructor.
    bool isInstantiated =
        compiler.codegenWorld.instantiatedClasses.contains(element);

    void visitField(Element holder, VariableElement field) {
      assert(invariant(element, field.isDeclaration));
      String name = field.name;

      // Keep track of whether or not we're dealing with a field mixin
      // into a native class.
      bool isMixinNativeField =
          isClass && element.isNative() && holder.isMixinApplication;

      // See if we can dynamically create getters and setters.
      // We can only generate getters and setters for [element] since
      // the fields of super classes could be overwritten with getters or
      // setters.
      bool needsGetter = false;
      bool needsSetter = false;
      if (isLibrary || isMixinNativeField || holder == element) {
        needsGetter = fieldNeedsGetter(field);
        needsSetter = fieldNeedsSetter(field);
      }

      if ((isInstantiated && !holder.isNative())
          || needsGetter
          || needsSetter) {
        String accessorName = namer.fieldAccessorName(field);
        String fieldName = namer.fieldPropertyName(field);
        bool needsCheckedSetter = false;
        if (compiler.enableTypeAssertions
            && needsSetter
            && !canAvoidGeneratedCheckedSetter(field)) {
          needsCheckedSetter = true;
          needsSetter = false;
        }
        // Getters and setters with suffixes will be generated dynamically.
        f(field, fieldName, accessorName, needsGetter, needsSetter,
          needsCheckedSetter);
      }
    }

    if (isLibrary) {
      LibraryElement library = element;
      library.implementation.forEachLocalMember((Element member) {
        if (member.isField()) visitField(library, member);
      });
    } else if (visitStatics) {
      ClassElement cls = element;
      cls.implementation.forEachStaticField(visitField);
    } else {
      ClassElement cls = element;
      // TODO(kasperl): We should make sure to only emit one version of
      // overridden fields. Right now, we rely on the ordering so the
      // fields pulled in from mixins are replaced with the fields from
      // the class definition.

      // If a class is not instantiated then we add the field just so we can
      // generate the field getter/setter dynamically. Since this is only
      // allowed on fields that are in [element] we don't need to visit
      // superclasses for non-instantiated classes.
      cls.implementation.forEachInstanceField(
          visitField, includeSuperAndInjectedMembers: isInstantiated);
    }
  }

  void recordMangledField(Element member,
                          String accessorName,
                          String memberName) {
    if (!backend.shouldRetainGetter(member)) return;
    String previousName;
    if (member.isInstanceMember()) {
      previousName = task.mangledFieldNames.putIfAbsent(
          '${namer.getterPrefix}$accessorName',
          () => memberName);
    } else {
      previousName = task.mangledGlobalFieldNames.putIfAbsent(
          accessorName,
          () => memberName);
    }
    assert(invariant(member, previousName == memberName,
                     message: '$previousName != ${memberName}'));
  }

  bool fieldNeedsGetter(VariableElement field) {
    assert(field.isField());
    if (fieldAccessNeverThrows(field)) return false;
    return backend.shouldRetainGetter(field)
        || compiler.codegenWorld.hasInvokedGetter(field, compiler);
  }

  bool fieldNeedsSetter(VariableElement field) {
    assert(field.isField());
    if (fieldAccessNeverThrows(field)) return false;
    return (!field.modifiers.isFinalOrConst())
        && (backend.shouldRetainSetter(field)
            || compiler.codegenWorld.hasInvokedSetter(field, compiler));
  }

  // We never access a field in a closure (a captured variable) without knowing
  // that it is there.  Therefore we don't need to use a getter (that will throw
  // if the getter method is missing), but can always access the field directly.
  static bool fieldAccessNeverThrows(VariableElement field) {
    return field is ClosureFieldElement;
  }

  bool canAvoidGeneratedCheckedSetter(Element member) {
    // We never generate accessors for top-level/static fields.
    if (!member.isInstanceMember()) return true;
    DartType type = member.computeType(compiler);
    return type.treatAsDynamic || (type.element == compiler.objectClass);
  }

  void generateCheckedSetter(Element member,
                             String fieldName,
                             String accessorName,
                             ClassBuilder builder) {
    jsAst.Expression code = backend.generatedCode[member];
    assert(code != null);
    String setterName = namer.setterNameFromAccessorName(accessorName);
    builder.addProperty(setterName, code);
    generateReflectionDataForFieldGetterOrSetter(
        member, setterName, builder, isGetter: false);
  }

  void generateGetter(Element member, String fieldName, String accessorName,
                      ClassBuilder builder) {
    String getterName = namer.getterNameFromAccessorName(accessorName);
    ClassElement cls = member.getEnclosingClass();
    String className = namer.getNameOfClass(cls);
    String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
    List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : [];
    task.precompiledFunction.add(
        js('$className.prototype.$getterName = #',
           js.fun(args, js.return_(js('$receiver.$fieldName')))));
    if (backend.isNeededForReflection(member)) {
      task.precompiledFunction.add(
          js('$className.prototype.$getterName.${namer.reflectableField} = 1'));
    }
  }

  void generateSetter(Element member, String fieldName, String accessorName,
                      ClassBuilder builder) {
    String setterName = namer.setterNameFromAccessorName(accessorName);
    ClassElement cls = member.getEnclosingClass();
    String className = namer.getNameOfClass(cls);
    String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this';
    List<String> args =
        backend.isInterceptedMethod(member) ? ['receiver', 'v'] : ['v'];
    task.precompiledFunction.add(
        js('$className.prototype.$setterName = #',
           js.fun(args, js.return_(js('$receiver.$fieldName = v')))));
    if (backend.isNeededForReflection(member)) {
      task.precompiledFunction.add(
          js('$className.prototype.$setterName.${namer.reflectableField} = 1'));
    }
  }

  void generateReflectionDataForFieldGetterOrSetter(Element member,
                                                    String name,
                                                    ClassBuilder builder,
                                                    {bool isGetter}) {
    Selector selector = isGetter
        ? new Selector.getter(member.name, member.getLibrary())
        : new Selector.setter(member.name, member.getLibrary());
    String reflectionName = task.getReflectionName(selector, name);
    if (reflectionName != null) {
      var reflectable =
          js(backend.isAccessibleByReflection(member) ? '1' : '0');
      builder.addProperty('+$reflectionName', reflectable);
    }
  }
}
