// 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 MetadataEmitter extends CodeEmitterHelper {
  /// A list of JS expressions that represent metadata, parameter names and
  /// type, and return types.
  final List<String> globalMetadata = [];

  /// A map used to canonicalize the entries of globalMetadata.
  final Map<String, int> globalMetadataMap = <String, int>{};

  /// The metadata function returns the metadata associated with
  /// [element] in generated code.  The metadata needs to be wrapped
  /// in a function as it refers to constants that may not have been
  /// constructed yet.  For example, a class is allowed to be
  /// annotated with itself.  The metadata function is used by
  /// mirrors_patch to implement DeclarationMirror.metadata.
  jsAst.Fun buildMetadataFunction(Element element) {
    if (!backend.retainMetadataOf(element)) return null;
    return compiler.withCurrentElement(element, () {
      var metadata = [];
      Link link = element.metadata;
      // TODO(ahe): Why is metadata sometimes null?
      if (link != null) {
        for (; !link.isEmpty; link = link.tail) {
          MetadataAnnotation annotation = link.head;
          Constant value = annotation.value;
          if (value == null) {
            compiler.reportInternalError(
                annotation, 'Internal error: value is null');
          } else {
            metadata.add(task.constantReference(value));
          }
        }
      }
      if (metadata.isEmpty) return null;
      return js.fun(
          [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]);
    });
  }

  jsAst.Node reifyDefaultArguments(FunctionElement function) {
    FunctionSignature signature = function.computeSignature(compiler);
    if (signature.optionalParameterCount == 0) return null;
    List<int> defaultValues = <int>[];
    for (Element element in signature.orderedOptionalParameters) {
      Constant value =
          compiler.constantHandler.initialVariableValues[element];
      String stringRepresentation = (value == null)
          ? "null"
          : jsAst.prettyPrint(task.constantReference(value), compiler)
              .getText();
      defaultValues.add(addGlobalMetadata(stringRepresentation));
    }
    return js.toExpression(defaultValues);
  }

  int reifyMetadata(MetadataAnnotation annotation) {
    Constant value = annotation.value;
    if (value == null) {
      compiler.reportInternalError(
          annotation, 'Internal error: value is null');
      return -1;
    }
    return addGlobalMetadata(
        jsAst.prettyPrint(task.constantReference(value), compiler).getText());
  }

  int reifyType(DartType type) {
    jsAst.Expression representation =
        backend.rti.getTypeRepresentation(type, (variable) {
          return js.toExpression(
              task.typeVariableHandler.reifyTypeVariable(variable.element));
        });

    return addGlobalMetadata(
        jsAst.prettyPrint(representation, compiler).getText());
  }

  int reifyName(String name) {
    return addGlobalMetadata('"$name"');
  }

  int addGlobalMetadata(String string) {
    return globalMetadataMap.putIfAbsent(string, () {
      globalMetadata.add(string);
      return globalMetadata.length - 1;
    });
  }

  void emitMetadata(CodeBuffer buffer) {
    var literals = backend.typedefTypeLiterals.toList();
    Elements.sortedByPosition(literals);
    var properties = [];
    for (TypedefElement literal in literals) {
      var key = namer.getNameX(literal);
      var value = js.toExpression(reifyType(literal.rawType));
      properties.add(new jsAst.Property(js.string(key), value));
    }
    var map = new jsAst.ObjectInitializer(properties);
    buffer.write(
        jsAst.prettyPrint(
            js('init.functionAliases = #', map).toStatement(), compiler));
    buffer.write('${N}init.metadata$_=$_[');
    for (var metadata in globalMetadata) {
      if (metadata is String) {
        if (metadata != 'null') {
          buffer.write(metadata);
        }
      } else {
        throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
      }
      buffer.write(',$n');
    }
    buffer.write('];$n');
  }

  jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) {
    if (!backend.retainMetadataOf(element)) return code;
    return compiler.withCurrentElement(element, () {
      List<int> metadata = <int>[];
      FunctionSignature signature = element.functionSignature;
      if (element.isConstructor()) {
        metadata.add(reifyType(element.getEnclosingClass().thisType));
      } else {
        metadata.add(reifyType(signature.returnType));
      }
      signature.forEachParameter((Element parameter) {
        metadata
            ..add(reifyName(parameter.name))
            ..add(reifyType(parameter.computeType(compiler)));
      });
      Link link = element.metadata;
      // TODO(ahe): Why is metadata sometimes null?
      if (link != null) {
        for (; !link.isEmpty; link = link.tail) {
          metadata.add(reifyMetadata(link.head));
        }
      }
      code.body.statements.add(js.string(metadata.join(',')).toStatement());
      return code;
    });
  }
}
