// 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 MetadataCollector {
  final Compiler _compiler;
  final Emitter _emitter;

  /// A list of JS expressions that represent metadata, parameter names and
  /// type variable types.
  final List<String> globalMetadata = <String>[];

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

  /// A map with lists of JS expressions, one list for each output unit. The
  /// entries represent types including function types and typedefs.
  final Map<OutputUnit, List<String>> types = <OutputUnit, List<String>>{};

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

  MetadataCollector(this._compiler, this._emitter);

  JavaScriptBackend get _backend => _compiler.backend;
  TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler;

  bool _mustEmitMetadataFor(Element element) {
    return _backend.mustRetainMetadata &&
        _backend.referencedFromMirrorSystem(element);
  }

  /// 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 (!_mustEmitMetadataFor(element)) return null;
    return _compiler.withCurrentElement(element, () {
      List<jsAst.Expression> metadata = <jsAst.Expression>[];
      Link link = element.metadata;
      // TODO(ahe): Why is metadata sometimes null?
      if (link != null) {
        for (; !link.isEmpty; link = link.tail) {
          MetadataAnnotation annotation = link.head;
          ConstantExpression constant =
              _backend.constants.getConstantForMetadata(annotation);
          if (constant == null) {
            _compiler.internalError(annotation, 'Annotation value is null.');
          } else {
            metadata.add(_emitter.constantReference(constant.value));
          }
        }
      }
      if (metadata.isEmpty) return null;
      return js('function() { return # }',
          new jsAst.ArrayInitializer(metadata));
    });
  }

  List<int> reifyDefaultArguments(FunctionElement function) {
    FunctionSignature signature = function.functionSignature;
    if (signature.optionalParameterCount == 0) return const [];
    List<int> defaultValues = <int>[];
    for (ParameterElement element in signature.optionalParameters) {
      ConstantExpression constant =
          _backend.constants.getConstantForVariable(element);
      String stringRepresentation = (constant == null)
          ? "null"
          : jsAst.prettyPrint(
              _emitter.constantReference(constant.value), _compiler).getText();
      defaultValues.add(addGlobalMetadata(stringRepresentation));
    }
    return defaultValues;
  }

  int reifyMetadata(MetadataAnnotation annotation) {
    ConstantExpression constant =
        _backend.constants.getConstantForMetadata(annotation);
    if (constant == null) {
      _compiler.internalError(annotation, 'Annotation value is null.');
      return -1;
    }
    return addGlobalMetadata(
        jsAst.prettyPrint(
            _emitter.constantReference(constant.value), _compiler).getText());
  }

  int reifyType(DartType type, {bool ignoreTypeVariables: false}) {
    return reifyTypeForOutputUnit(type,
                                  _compiler.deferredLoadTask.mainOutputUnit,
                                  ignoreTypeVariables: ignoreTypeVariables);
  }

  int reifyTypeForOutputUnit(DartType type, OutputUnit outputUnit,
                             {bool ignoreTypeVariables: false}) {
    jsAst.Expression representation =
        _backend.rti.getTypeRepresentation(
            type,
            (variable) {
              if (ignoreTypeVariables) return new jsAst.LiteralNull();
              return js.number(
                  _typeVariableHandler.reifyTypeVariable(
                      variable.element));
            },
            (TypedefType typedef) {
              return _backend.isAccessibleByReflection(typedef.element);
            });

    return addTypeInOutputUnit(
        jsAst.prettyPrint(representation, _compiler).getText(), outputUnit);
  }

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

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

  int addTypeInOutputUnit(String compiledType, OutputUnit outputUnit) {
    if (_typesMap[outputUnit] == null) {
      _typesMap[outputUnit] = <String, int>{};
    }
    return _typesMap[outputUnit].putIfAbsent(compiledType, () {

      if (types[outputUnit] == null)
        types[outputUnit] = <String>[];

      types[outputUnit].add(compiledType);
      return types[outputUnit].length - 1;
    });
  }

  List<int> computeMetadata(FunctionElement element) {
    return _compiler.withCurrentElement(element, () {
      if (!_mustEmitMetadataFor(element)) return const <int>[];
      List<int> metadata = <int>[];
      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));
        }
      }
      return metadata;
    });
  }
}
