// Copyright (c) 2012, 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 js_backend;

class NativeEmitter {

  CodeEmitterTask emitter;
  CodeBuffer nativeBuffer;

  // Classes that participate in dynamic dispatch. These are the
  // classes that contain used members.
  Set<ClassElement> classesWithDynamicDispatch;

  // Native classes found in the application.
  Set<ClassElement> nativeClasses;

  // Caches the native subtypes of a native class.
  Map<ClassElement, List<ClassElement>> subtypes;

  // Caches the direct native subtypes of a native class.
  Map<ClassElement, List<ClassElement>> directSubtypes;

  // Caches the methods that have a native body.
  Set<FunctionElement> nativeMethods;

  // Do we need the native emitter to take care of handling
  // noSuchMethod for us? This flag is set to true in the emitter if
  // it finds any native class that needs noSuchMethod handling.
  bool handleNoSuchMethod = false;

  NativeEmitter(this.emitter)
      : classesWithDynamicDispatch = new Set<ClassElement>(),
        nativeClasses = new Set<ClassElement>(),
        subtypes = new Map<ClassElement, List<ClassElement>>(),
        directSubtypes = new Map<ClassElement, List<ClassElement>>(),
        nativeMethods = new Set<FunctionElement>(),
        nativeBuffer = new CodeBuffer();

  Compiler get compiler => emitter.compiler;
  JavaScriptBackend get backend => compiler.backend;

  String get _ => emitter._;
  String get n => emitter.n;
  String get N => emitter.N;

  String get dynamicName {
    Element element = compiler.findHelper(
        const SourceString('dynamicFunction'));
    return backend.namer.isolateAccess(element);
  }

  String get dynamicFunctionTableName {
    Element element = compiler.findHelper(
        const SourceString('dynamicFunctionTable'));
    return backend.namer.isolateAccess(element);
  }

  String get dynamicSetMetadataName {
    Element element = compiler.findHelper(
        const SourceString('dynamicSetMetadata'));
    return backend.namer.isolateAccess(element);
  }

  String get typeNameOfName {
    Element element = compiler.findHelper(
        const SourceString('getTypeNameOf'));
    return backend.namer.isolateAccess(element);
  }

  String get defPropName {
    Element element = compiler.findHelper(
        const SourceString('defineProperty'));
    return backend.namer.isolateAccess(element);
  }

  String get toStringHelperName {
    Element element = compiler.findHelper(
        const SourceString('toStringForNativeObject'));
    return backend.namer.isolateAccess(element);
  }

  String get hashCodeHelperName {
    Element element = compiler.findHelper(
        const SourceString('hashCodeForNativeObject'));
    return backend.namer.isolateAccess(element);
  }

  String get dispatchPropertyNameVariable {
    Element element = compiler.findInterceptor(
        const SourceString('dispatchPropertyName'));
    return backend.namer.isolateAccess(element);
  }

  String get defineNativeMethodsName {
    Element element = compiler.findHelper(
        const SourceString('defineNativeMethods'));
    return backend.namer.isolateAccess(element);
  }

  String get defineNativeMethodsNonleafName {
    Element element = compiler.findHelper(
        const SourceString('defineNativeMethodsNonleaf'));
    return backend.namer.isolateAccess(element);
  }

  String get defineNativeMethodsFinishName {
    Element element = compiler.findHelper(
        const SourceString('defineNativeMethodsFinish'));
    return backend.namer.isolateAccess(element);
  }

  bool isNativeGlobal(String quotedName) {
    return identical(quotedName[1], '@');
  }

  String toNativeTag(ClassElement cls) {
    String quotedName = cls.nativeTagInfo.slowToString();
    if (isNativeGlobal(quotedName)) {
      // Global object, just be like the other types for now.
      return quotedName.substring(3, quotedName.length - 1);
    } else {
      return quotedName.substring(2, quotedName.length - 1);
    }
  }

  void generateNativeClass(ClassElement classElement, CodeBuffer mainBuffer) {
    assert(!classElement.hasBackendMembers);
    nativeClasses.add(classElement);

    ClassElement superclass = classElement.superclass;
    assert(superclass != null);
    // Fix superclass.  TODO(sra): make native classes inherit from Interceptor.
    if (superclass == compiler.objectClass) {
      superclass = backend.jsInterceptorClass;
    }

    String superName = backend.namer.getName(superclass);

    ClassBuilder builder = new ClassBuilder();
    emitter.emitClassConstructor(classElement, builder);
    emitter.emitSuper(superName, builder);
    bool hasFields = emitter.emitClassFields(classElement, builder,
        classIsNative: true,
        superClass: superName);
    emitter.emitClassGettersSetters(classElement, builder);
    emitter.emitInstanceMembers(classElement, builder);

    // An empty native class may be omitted since the superclass methods can be
    // located via the dispatch metadata.
    // TODO(sra): Also need to check there are no subclasses that will reference
    // this class.
    // bool hasOnlyGeneratedFields = builder.properties.length == 1;
    // if (hasOnlyGeneratedFields == 1 && !hasFields) return;

    // Define interceptor class for [classElement].
    String className = backend.namer.getName(classElement);
    jsAst.Expression init =
        js(emitter.classesCollector)[className].assign(
            builder.toObjectInitializer());
    mainBuffer.write(jsAst.prettyPrint(init, compiler));
    mainBuffer.write('$N$n');

    emitter.needsDefineClass = true;

    // Define dispatch for [classElement].
    String nativeTag = toNativeTag(classElement);
    String definer = directSubtypes[classElement] == null
        ? defineNativeMethodsName
        : defineNativeMethodsNonleafName;

    // TODO(sra): Fix DOM generation.  There is a missing proto in the picture
    // the DOM gives of the proto chain.  We might need an annotation.
    if (nativeTag == 'HTMLElement') definer = defineNativeMethodsNonleafName;

    jsAst.Expression definition =
        js(definer)(
            [js.string(nativeTag),
             js(backend.namer.isolateAccess(classElement))]);

    nativeBuffer.add(jsAst.prettyPrint(definition, compiler));
    nativeBuffer.add('$N$n');

    classesWithDynamicDispatch.add(classElement);
  }

  void finishGenerateNativeClasses() {
    // TODO(sra): Put specialized version of getNativeMethods on
    // `Object.prototype` to avoid checking in `getInterceptor` and
    // specializations.

    // jsAst.Expression call = js(defineNativeMethodsFinishName)([]);
    // nativeBuffer.add(jsAst.prettyPrint(call, compiler));
    // nativeBuffer.add('$N$n');
  }

  List<ClassElement> getDirectSubclasses(ClassElement cls) {
    List<ClassElement> result = directSubtypes[cls];
    return result == null ? const<ClassElement>[] : result;
  }

  void potentiallyConvertDartClosuresToJs(
      List<jsAst.Statement> statements,
      FunctionElement member,
      List<jsAst.Parameter> stubParameters) {
    FunctionSignature parameters = member.computeSignature(compiler);
    Element converter =
        compiler.findHelper(const SourceString('convertDartClosureToJS'));
    String closureConverter = backend.namer.isolateAccess(converter);
    Set<String> stubParameterNames = new Set<String>.from(
        stubParameters.map((param) => param.name));
    parameters.forEachParameter((Element parameter) {
      String name = parameter.name.slowToString();
      // If [name] is not in [stubParameters], then the parameter is an optional
      // parameter that was not provided for this stub.
      for (jsAst.Parameter stubParameter in stubParameters) {
        if (stubParameter.name == name) {
          DartType type = parameter.computeType(compiler).unalias(compiler);
          if (type is FunctionType) {
            // The parameter type is a function type either directly or through
            // typedef(s).
            int arity = type.computeArity();
            statements.add(
                js('$name = $closureConverter($name, $arity)').toStatement());
            break;
          }
        }
      }
    });
  }

  List<jsAst.Statement> generateParameterStubStatements(
      Element member,
      bool isInterceptedMethod,
      String invocationName,
      List<jsAst.Parameter> stubParameters,
      List<jsAst.Expression> argumentsBuffer,
      int indexOfLastOptionalArgumentInParameters) {
    // The target JS function may check arguments.length so we need to
    // make sure not to pass any unspecified optional arguments to it.
    // For example, for the following Dart method:
    //   foo([x, y, z]);
    // The call:
    //   foo(y: 1)
    // must be turned into a JS call to:
    //   foo(null, y).

    ClassElement classElement = member.enclosingElement;
    String nativeTagInfo = classElement.nativeTagInfo.slowToString();

    List<jsAst.Statement> statements = <jsAst.Statement>[];
    potentiallyConvertDartClosuresToJs(statements, member, stubParameters);

    String target;
    jsAst.Expression receiver;
    List<jsAst.Expression> arguments;

    if (!nativeMethods.contains(member)) {
      // When calling a method that has a native body, we call it with our
      // calling conventions.
      target = backend.namer.getName(member);
      arguments = argumentsBuffer;
    } else {
      // When calling a JS method, we call it with the native name, and only the
      // arguments up until the last one provided.
      target = member.fixedBackendName();

      if (isInterceptedMethod) {
        receiver = argumentsBuffer[0];
        arguments = argumentsBuffer.sublist(1,
            indexOfLastOptionalArgumentInParameters + 1);
      } else {
        receiver = js('this');
        arguments = argumentsBuffer.sublist(0,
            indexOfLastOptionalArgumentInParameters + 1);
      }
    }
    statements.add(new jsAst.Return(receiver[target](arguments)));

    return statements;
  }

  void emitDynamicDispatchMetadata() {
    if (classesWithDynamicDispatch.isEmpty) return;
    int length = classesWithDynamicDispatch.length;
    if (!compiler.enableMinification) {
      nativeBuffer.add('// $length dynamic classes.\n');
    }

    // Build a pre-order traversal over all the classes and their subclasses.
    Set<ClassElement> seen = new Set<ClassElement>();
    List<ClassElement> classes = <ClassElement>[];
    void visit(ClassElement cls) {
      if (seen.contains(cls)) return;
      seen.add(cls);
      getDirectSubclasses(cls).forEach(visit);
      classes.add(cls);
    }
    Elements.sortedByPosition(classesWithDynamicDispatch).forEach(visit);

    List<ClassElement> preorderDispatchClasses = classes.where(
        (cls) => !getDirectSubclasses(cls).isEmpty &&
                  classesWithDynamicDispatch.contains(cls)).toList();

    if (!compiler.enableMinification) {
      nativeBuffer.add('// ${classes.length} classes\n');
    }
    Iterable<ClassElement> classesThatHaveSubclasses = classes.where(
        (ClassElement t) => !getDirectSubclasses(t).isEmpty);
    if (!compiler.enableMinification) {
      nativeBuffer.add('// ${classesThatHaveSubclasses.length} !leaf\n');
    }

    // Generate code that builds the map from cls tags used in dynamic dispatch
    // to the set of cls tags of classes that extend (TODO: or implement) those
    // classes.  The set is represented as a string of tags joined with '|'.
    // This is easily split into an array of tags, or converted into a regexp.
    //
    // To reduce the size of the sets, subsets are CSE-ed out into variables.
    // The sets could be much smaller if we could make assumptions about the
    // cls tags of other classes (which are constructor names or part of the
    // result of Object.protocls.toString).  For example, if objects that are
    // Dart objects could be easily excluded, then we might be able to simplify
    // the test, replacing dozens of HTMLxxxElement classes with the regexp
    // /HTML.*Element/.

    // Temporary variables for common substrings.
    List<String> varNames = <String>[];
    // Values of temporary variables.
    Map<String, jsAst.Expression> varDefns = new Map<String, jsAst.Expression>();

    // Expression to compute tags string for a class.  The expression will
    // initially be a string or expression building a string, but may be
    // replaced with a variable reference to the common substring.
    Map<ClassElement, jsAst.Expression> tagDefns =
        new Map<ClassElement, jsAst.Expression>();

    jsAst.Expression makeExpression(ClassElement classElement) {
      // Expression fragments for this set of cls keys.
      List<jsAst.Expression> expressions = <jsAst.Expression>[];
      // TODO: Remove if cls is abstract.
      List<String> subtags = [toNativeTag(classElement)];
      void walk(ClassElement cls) {
        for (final ClassElement subclass in getDirectSubclasses(cls)) {
          ClassElement tag = subclass;
          jsAst.Expression existing = tagDefns[tag];
          if (existing == null) {
            // [subclass] is still within the subtree between dispatch classes.
            subtags.add(toNativeTag(tag));
            walk(subclass);
          } else {
            // [subclass] is one of the preorderDispatchClasses, so CSE this
            // reference with the previous reference.
            jsAst.VariableUse use = existing.asVariableUse();
            if (use != null && varDefns.containsKey(use.name)) {
              // We end up here if the subclasses have a DAG structure.  We
              // don't have DAGs yet, but if the dispatch is used for mixins
              // that will be a possibility.
              // Re-use the previously created temporary variable.
              expressions.add(js(use.name));
            } else {
              String varName = 'v${varNames.length}_${tag.name.slowToString()}';
              varNames.add(varName);
              varDefns[varName] = existing;
              tagDefns[tag] = js(varName);
              expressions.add(js(varName));
            }
          }
        }
      }
      walk(classElement);

      if (!subtags.isEmpty) {
        subtags.sort();
        expressions.add(js.string(subtags.join('|')));
      }
      jsAst.Expression expression;
      if (expressions.length == 1) {
        expression = expressions[0];
      } else {
        jsAst.Expression array = new jsAst.ArrayInitializer.from(expressions);
        expression = array['join']([js.string('|')]);
      }
      return expression;
    }

    for (final ClassElement classElement in preorderDispatchClasses) {
      tagDefns[classElement] = makeExpression(classElement);
    }

    // Write out a thunk that builds the metadata.
    if (!tagDefns.isEmpty) {
      List<jsAst.Statement> statements = <jsAst.Statement>[];

      List<jsAst.VariableInitialization> initializations =
          <jsAst.VariableInitialization>[];
      for (final String varName in varNames) {
        initializations.add(
            new jsAst.VariableInitialization(
                new jsAst.VariableDeclaration(varName),
                varDefns[varName]));
      }
      if (!initializations.isEmpty) {
        statements.add(
            new jsAst.ExpressionStatement(
                new jsAst.VariableDeclarationList(initializations)));
      }

      // [table] is a list of lists, each inner list of the form:
      //   [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
      // E.g.
      //   [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
      jsAst.Expression table =
          new jsAst.ArrayInitializer.from(
              preorderDispatchClasses.map((cls) =>
                  new jsAst.ArrayInitializer.from([
                      js.string(toNativeTag(cls)),
                      tagDefns[cls]])));

      statements.add(js('$dynamicSetMetadataName(#)', table).toStatement());

      //  (function(){statements})();
      if (emitter.compiler.enableMinification) nativeBuffer.add(';');
      nativeBuffer.add(
          jsAst.prettyPrint(
              new jsAst.ExpressionStatement(
                  new jsAst.Call(new jsAst.Fun([], new jsAst.Block(statements)),
                                 [])),
              compiler));
    }
  }

  bool isSupertypeOfNativeClass(Element element) {
    if (element.isTypeVariable()) {
      compiler.cancel("Is check for type variable", element: element);
      return false;
    }
    if (element.computeType(compiler).unalias(compiler) is FunctionType) {
      // The element type is a function type either directly or through
      // typedef(s).
      return false;
    }

    if (!element.isClass()) {
      compiler.cancel("Is check does not handle element", element: element);
      return false;
    }

    return subtypes[element] != null;
  }

  bool requiresNativeIsCheck(Element element) {
    if (!element.isClass()) return false;
    ClassElement cls = element;
    if (cls.isNative()) return true;
    return isSupertypeOfNativeClass(element);
  }

  void assembleCode(CodeBuffer targetBuffer) {
    List<jsAst.Property> objectProperties = <jsAst.Property>[];

    void addProperty(String name, jsAst.Expression value) {
      objectProperties.add(new jsAst.Property(js.string(name), value));
    }

    // Because of native classes, we have to generate some is checks
    // by calling a method, instead of accessing a property. So we
    // attach to the JS Object prototype these methods that return
    // false, and will be overridden by subclasses when they have to
    // return true.
    void emitIsChecks() {
      for (ClassElement element in
               Elements.sortedByPosition(emitter.checkedClasses)) {
        if (!requiresNativeIsCheck(element)) continue;
        if (element.isObject(compiler)) continue;
        // Add function for the is-test.
        String name = backend.namer.operatorIs(element);
        addProperty(name,
            js.fun([], js.return_(js('false'))));
        // Add a function for the (trivial) substitution.
        addProperty(backend.namer.substitutionName(element),
                    js.fun([], js.return_(js('null'))));
      }
    }
    emitIsChecks();

    if (!nativeClasses.isEmpty) {
      emitDynamicDispatchMetadata();

      // If the native emitter has been asked to take care of the
      // noSuchMethod handlers, we do that now.
      if (handleNoSuchMethod) {
        emitter.emitNoSuchMethodHandlers(addProperty);
      }
    }

    // If we have any properties to add to Object.prototype, we run
    // through them and add them using defineProperty.
    if (!objectProperties.isEmpty) {
      jsAst.Expression init =
          js.fun(['table'],
              new jsAst.ForIn(
                  new jsAst.VariableDeclarationList(
                      [new jsAst.VariableInitialization(
                          new jsAst.VariableDeclaration('key'),
                          null)]),
                  js('table'),
                  new jsAst.ExpressionStatement(
                      js('$defPropName(Object.prototype, key, table[key])'))))(
              new jsAst.ObjectInitializer(objectProperties));

      if (emitter.compiler.enableMinification) targetBuffer.add(';');
      targetBuffer.add(jsAst.prettyPrint(
          new jsAst.ExpressionStatement(init), compiler));
      targetBuffer.add('\n');
    }

    targetBuffer.add(nativeBuffer);
    targetBuffer.add('\n');
  }
}
