// 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 dump_info;

import 'dart:convert' show
    HtmlEscape,
    JsonEncoder,
    StringConversionSink,
    ChunkedConversionSink;

import 'elements/elements.dart';
import 'elements/visitor.dart';
import 'dart2jslib.dart' show
    Backend,
    CodeBuffer,
    Compiler,
    CompilerTask,
    MessageKind;
import 'types/types.dart' show TypeMask;
import 'deferred_load.dart' show OutputUnit;
import 'js_backend/js_backend.dart' show JavaScriptBackend;
import 'js/js.dart' as jsAst;
import 'universe/universe.dart' show Selector;
import 'util/util.dart' show NO_LOCATION_SPANNABLE;

/// Maps objects to an id.  Supports lookups in
/// both directions.
class IdMapper<T>{
  Map<int, T> _idToElement = {};
  Map<T, int> _elementToId = {};
  int _idCounter = 0;
  String name;

  IdMapper(this.name);

  Iterable<T> get elements => _elementToId.keys;

  String add(T e) {
    if (_elementToId.containsKey(e)) {
      return name + "/${_elementToId[e]}";
    }

    _idToElement[_idCounter] = e;
    _elementToId[e] = _idCounter;
    _idCounter += 1;
    return name + "/${_idCounter - 1}";
  }
}

class GroupedIdMapper {
  // Mappers for specific kinds of elements.
  IdMapper<LibraryElement> _library = new IdMapper('library');
  IdMapper<TypedefElement> _typedef = new IdMapper('typedef');
  IdMapper<FieldElement> _field = new IdMapper('field');
  IdMapper<ClassElement> _class = new IdMapper('class');
  IdMapper<FunctionElement> _function = new IdMapper('function');
  IdMapper<OutputUnit> _outputUnit = new IdMapper('outputUnit');

  Iterable<Element> get functions => _function.elements;

  // Convert this database of elements into JSON for rendering
  Map<String, dynamic> _toJson(ElementToJsonVisitor elementToJson) {
    Map<String, dynamic> json = {};
    var m = [_library, _typedef, _field, _class, _function];
    for (IdMapper mapper in m) {
      Map<String, dynamic> innerMapper = {};
      mapper._idToElement.forEach((k, v) {
        // All these elements are already cached in the
        // jsonCache, so this is just an access.
        var elementJson = elementToJson.process(v);
        if (elementJson != null) {
          innerMapper["$k"] = elementJson;
        }
      });
      json[mapper.name] = innerMapper;
    }
    return json;
  }
}

class ElementToJsonVisitor extends ElementVisitor<Map<String, dynamic>> {
  final GroupedIdMapper mapper = new GroupedIdMapper();
  final Compiler compiler;

  final Map<Element, Map<String, dynamic>> jsonCache = {};

  String dart2jsVersion;

  ElementToJsonVisitor(this.compiler);

  void run() {
    Backend backend = compiler.backend;

    dart2jsVersion = compiler.hasBuildId ? compiler.buildId : null;

    for (var library in compiler.libraryLoader.libraries.toList()) {
      library.accept(this);
    }
  }

  // If keeping the element is in question (like if a function has a size
  // of zero), only keep it if it holds dependencies to elsewhere.
  bool shouldKeep(Element element) {
    return compiler.dumpInfoTask.selectorsFromElement.containsKey(element)
        || compiler.dumpInfoTask.inlineCount.containsKey(element);
  }

  Map<String, dynamic> toJson() {
    return mapper._toJson(this);
  }

  // Memoization of the JSON creating process.
  Map<String, dynamic> process(Element element) {
    return jsonCache.putIfAbsent(element, () => element.accept(this));
  }

  // Returns the id of an [element] if it has already been processed.
  // If the element has not been processed, this function does not
  // process it, and simply returns null instead.
  String idOf(Element element) {
    if (jsonCache.containsKey(element) && jsonCache[element] != null) {
      return jsonCache[element]['id'];
    } else {
      return null;
    }
  }

  Map<String, dynamic> visitElement(Element element) {
    return null;
  }

  Map<String, dynamic> visitConstructorBodyElement(ConstructorBodyElement e) {
    return visitFunctionElement(e.constructor);
  }

  Map<String, dynamic> visitLibraryElement(LibraryElement element) {
    var id = mapper._library.add(element);
    List<String> children = <String>[];

    String libname = element.getLibraryName();
    libname = libname == "" ? "<unnamed>" : libname;

    int size = compiler.dumpInfoTask.sizeOf(element);

    LibraryElement contentsOfLibrary = element.isPatched
      ? element.patch : element;
    contentsOfLibrary.forEachLocalMember((Element member) {
      Map<String, dynamic> childJson = this.process(member);
      if (childJson == null) return;
      children.add(childJson['id']);
    });

    if (children.length == 0 && !shouldKeep(element)) {
      return null;
    }

    return {
      'kind': 'library',
      'name': libname,
      'size': size,
      'id': id,
      'children': children
    };
  }

  Map<String, dynamic> visitTypedefElement(TypedefElement element) {
    String id = mapper._typedef.add(element);
    return element.alias == null
      ? null
      : {
        'id': id,
        'type': element.alias.toString(),
        'kind': 'typedef',
        'name': element.name
      };
  }

  Map<String, dynamic> visitFieldElement(FieldElement element) {
    String id = mapper._field.add(element);
    List<String> children = [];
    StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);

    TypeMask inferredType =
        compiler.typesTask.getGuaranteedTypeOfElement(element);
    // If a field has an empty inferred type it is never used.
    if (inferredType == null || inferredType.isEmpty || element.isConst) {
      return null;
    }

    int size = compiler.dumpInfoTask.sizeOf(element);
    String code;

    if (emittedCode != null) {
      size += emittedCode.length;
      code = emittedCode.toString();
    }

    for (Element closure in element.nestedClosures) {
      var childJson = this.process(closure);
      if (childJson != null) {
        children.add(childJson['id']);
        if (childJson.containsKey('size')) {
          size += childJson['size'];
        }
      }
    }

    OutputUnit outputUnit =
        compiler.deferredLoadTask.outputUnitForElement(element);

    return {
      'id': id,
      'kind': 'field',
      'type': element.type.toString(),
      'inferredType': inferredType.toString(),
      'name': element.name,
      'children': children,
      'size': size,
      'code': code,
      'outputUnit': mapper._outputUnit.add(outputUnit)
    };
  }

  Map<String, dynamic> visitClassElement(ClassElement element) {
    String id = mapper._class.add(element);
    List<String> children = [];

    int size = compiler.dumpInfoTask.sizeOf(element);
    JavaScriptBackend backend = compiler.backend;

    Map<String, dynamic> modifiers = { 'abstract': element.isAbstract };

    element.forEachLocalMember((Element member) {
      Map<String, dynamic> childJson = this.process(member);
      if (childJson != null) {
        children.add(childJson['id']);

        // Closures are placed in the library namespace, but
        // we want to attribute them to a function, and by
        // extension, this class.  Process and add the sizes
        // here.
        if (member is MemberElement) {
          for (Element closure in member.nestedClosures) {
            Map<String, dynamic> child = this.process(closure);

            // Look for the parent element of this closure which should
            // be a class.  If it exists, set the display name to
            // the name of the class + the name of the closure function.
            Element parent = closure.enclosingElement;
            Map<String, dynamic> processedParent = this.process(parent);
            if (processedParent != null) {
              child['name'] = "${processedParent['name']}.${child['name']}";
            }

            if (child != null) {
              size += child['size'];
            }
          }
        }
      }
    });

    // Omit element if it is not needed.
    if (!backend.emitter.neededClasses.contains(element) &&
        children.length == 0) {
      return null;
    }

    OutputUnit outputUnit =
        compiler.deferredLoadTask.outputUnitForElement(element);

    return {
      'name': element.name,
      'size': size,
      'kind': 'class',
      'modifiers': modifiers,
      'children': children,
      'id': id,
      'outputUnit': mapper._outputUnit.add(outputUnit)
    };
  }

  Map<String, dynamic> visitFunctionElement(FunctionElement element) {
    String id = mapper._function.add(element);
    String name = element.name;
    String kind = "function";
    List<String> children = [];
    List<Map<String, dynamic>> parameters = [];
    String inferredReturnType = null;
    String returnType = null;
    String sideEffects = null;
    String code = "";

    StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
    int size = compiler.dumpInfoTask.sizeOf(element);

    Map<String, dynamic> modifiers = {
      'static': element.isStatic,
      'const': element.isConst,
      'factory': element.isFactoryConstructor,
      'external': element.isPatched
    };

    var enclosingElement = element.enclosingElement;
    if (enclosingElement.isField ||
               enclosingElement.isFunction ||
               element.isClosure ||
               enclosingElement.isConstructor) {
      kind = "closure";
      name = "<unnamed>";
    } else if (modifiers['static']) {
      kind = 'function';
    } else if (enclosingElement.isClass) {
      kind = 'method';
    }

    if (element.isConstructor) {
      name == ""
        ? "${element.enclosingElement.name}"
        : "${element.enclosingElement.name}.${element.name}";
      kind = "constructor";
    }

    if (emittedCode != null) {
      FunctionSignature signature = element.functionSignature;
      returnType = signature.type.returnType.toString();
      signature.forEachParameter((parameter) {
        parameters.add({
          'name': parameter.name,
          'type': compiler.typesTask
            .getGuaranteedTypeOfElement(parameter).toString(),
          'declaredType': parameter.node.type.toString()
        });
      });
      inferredReturnType = compiler.typesTask
        .getGuaranteedReturnTypeOfElement(element).toString();
      sideEffects = compiler.world.getSideEffectsOfElement(element).toString();
      code = emittedCode.toString();
    }

    if (element is MemberElement) {
      MemberElement member = element as MemberElement;
      for (Element closure in member.nestedClosures) {
        Map<String, dynamic> child = this.process(closure);
        if (child != null) {
          child['kind'] = 'closure';
          children.add(child['id']);
          size += child['size'];
        }
      }
    }

    if (size == 0 && !shouldKeep(element)) {
      return null;
    }

    int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
    if (inlinedCount == null) {
      inlinedCount = 0;
    }

    OutputUnit outputUnit =
        compiler.deferredLoadTask.outputUnitForElement(element);

    return {
      'kind': kind,
      'name': name,
      'id': id,
      'modifiers': modifiers,
      'children': children,
      'size': size,
      'returnType': returnType,
      'inferredReturnType': inferredReturnType,
      'parameters': parameters,
      'sideEffects': sideEffects,
      'inlinedCount': inlinedCount,
      'code': code,
      'type': element.type.toString(),
      'outputUnit': mapper._outputUnit.add(outputUnit)
    };
  }
}

class Selection {
  final Element selectedElement;
  final Selector selector;
  Selection(this.selectedElement, this.selector);
}

class DumpInfoTask extends CompilerTask {
  DumpInfoTask(Compiler compiler)
      : super(compiler);

  String name = "Dump Info";

  ElementToJsonVisitor infoCollector;

  /// The size of the generated output.
  int _programSize;

  // A set of javascript AST nodes that we care about the size of.
  // This set is automatically populated when registerElementAst()
  // is called.
  final Set<jsAst.Node> _tracking = new Set<jsAst.Node>();
  // A mapping from Dart Elements to Javascript AST Nodes.
  final Map<Element, List<jsAst.Node>> _elementToNodes =
    <Element, List<jsAst.Node>>{};
  // A mapping from Javascript AST Nodes to the size of their
  // pretty-printed contents.
  final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
  final Map<jsAst.Node, int> _nodeBeforeSize = <jsAst.Node, int>{};
  final Map<Element, int> _fieldNameToSize = <Element, int>{};

  final Map<Element, Set<Selector>> selectorsFromElement = {};
  final Map<Element, int> inlineCount = <Element, int>{};
  // A mapping from an element to a list of elements that are
  // inlined inside of it.
  final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{};

  /// Register the size of the generated output.
  void reportSize(int programSize) {
    _programSize = programSize;
  }

  void registerInlined(Element element, Element inlinedFrom) {
    inlineCount.putIfAbsent(element, () => 0);
    inlineCount[element] += 1;
    inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>());
    inlineMap[inlinedFrom].add(element);
  }

  /**
   * Registers that a function uses a selector in the
   * function body
   */
  void elementUsesSelector(Element element, Selector selector) {
    if (compiler.dumpInfo) {
      selectorsFromElement
          .putIfAbsent(element, () => new Set<Selector>())
          .add(selector);
    }
  }

  /**
   * Returns an iterable of [Selection]s that are used by
   * [element].  Each [Selection] contains an element that is
   * used and the selector that selected the element.
   */
  Iterable<Selection> getRetaining(Element element) {
    if (!selectorsFromElement.containsKey(element)) {
      return const <Selection>[];
    } else {
      return selectorsFromElement[element].expand(
        (selector) {
          return compiler.world.allFunctions.filter(selector).map((element) {
            return new Selection(element, selector);
          });
        });
    }
  }

  /**
   * A callback that can be called before a jsAst [node] is
   * pretty-printed. The size of the code buffer ([aftersize])
   * is also passed.
   */
  void enteringAst(jsAst.Node node, int beforeSize) {
    if (isTracking(node)) {
      _nodeBeforeSize[node] = beforeSize;
    }
  }

  /**
   * A callback that can be called after a jsAst [node] is
   * pretty-printed. The size of the code buffer ([aftersize])
   * is also passed.
   */
  void exitingAst(jsAst.Node node, int afterSize) {
    if (isTracking(node)) {
      int diff = afterSize - _nodeBeforeSize[node];
      recordAstSize(node, diff);
    }
  }

  // Returns true if we care about tracking the size of
  // this node.
  bool isTracking(jsAst.Node code) {
    if (compiler.dumpInfo) {
      return _tracking.contains(code);
    } else {
      return false;
    }
  }

  // Registers that a javascript AST node `code` was produced by the
  // dart Element `element`.
  void registerElementAst(Element element, jsAst.Node code) {
    if (compiler.dumpInfo) {
      _elementToNodes
        .putIfAbsent(element, () => new List<jsAst.Node>())
        .add(code);
      _tracking.add(code);
    }
  }

  // Records the size of a dart AST node after it has been
  // pretty-printed into the output buffer.
  void recordAstSize(jsAst.Node code, int size) {
    if (compiler.dumpInfo) {
      //TODO: should I be incrementing here instead?
      _nodeToSize[code] = size;
    }
  }

  // Field names are treated differently by the dart compiler
  // so they must be recorded seperately.
  void recordFieldNameSize(Element element, int size) {
    _fieldNameToSize[element] = size;
  }

  // Returns the size of the source code that
  // was generated for an element.  If no source
  // code was produced, return 0.
  int sizeOf(Element element) {
    if (_fieldNameToSize.containsKey(element)) {
      return _fieldNameToSize[element];
    }
    if (_elementToNodes.containsKey(element)) {
      return _elementToNodes[element]
        .map(sizeOfNode)
        .fold(0, (a, b) => a + b);
    } else {
      return 0;
    }
  }

  int sizeOfNode(jsAst.Node node) {
    if (_nodeToSize.containsKey(node)) {
      return _nodeToSize[node];
    } else {
      return 0;
    }
  }

  StringBuffer codeOf(Element element) {
    List<jsAst.Node> code = _elementToNodes[element];
    if (code == null) return null;
    // Concatenate rendered ASTs.
    StringBuffer sb = new StringBuffer();
    for (jsAst.Node ast in code) {
      sb.writeln(jsAst.prettyPrint(ast, compiler).getText());
    }
    return sb;
  }

  void collectInfo() {
    infoCollector = new ElementToJsonVisitor(compiler)..run();
  }

  void dumpInfo() {
    measure(() {
      if (infoCollector == null) {
        collectInfo();
      }

      StringBuffer jsonBuffer = new StringBuffer();
      dumpInfoJson(jsonBuffer);
      compiler.outputProvider('', 'info.json')
        ..add(jsonBuffer.toString())
        ..close();
    });
  }


  void dumpInfoJson(StringSink buffer) {
    JsonEncoder encoder = const JsonEncoder();
    DateTime startToJsonTime = new DateTime.now();

    Map<String, List<Map<String, String>>> holding =
        <String, List<Map<String, String>>>{};
    for (Element fn in infoCollector.mapper.functions) {
      Iterable<Selection> pulling = getRetaining(fn);
      // Don't bother recording an empty list of dependencies.
      if (pulling.length > 0) {
        String fnId = infoCollector.idOf(fn);
        // Some dart2js builtin functions are not
        // recorded.  Don't register these.
        if (fnId != null) {
          holding[fnId] = pulling
            .map((selection) {
              return <String, String>{
                "id": infoCollector.idOf(selection.selectedElement),
                "mask": selection.selector.mask.toString()
              };
            })
            // Filter non-null ids for the same reason as above.
            .where((a) => a['id'] != null)
            .toList();
        }
      }
    }

    // Track dependencies that come from inlining.
    for (Element element in inlineMap.keys) {
      String keyId = infoCollector.idOf(element);
      if (keyId != null) {
        for (Element held in inlineMap[element]) {
          String valueId = infoCollector.idOf(held);
          if (valueId != null) {
            holding.putIfAbsent(keyId, () => new List<Map<String, String>>())
              .add(<String, String>{
                "id": valueId,
                "mask": "inlined"
              });
          }
        }
      }
    }

    List<Map<String, dynamic>> outputUnits =
        new List<Map<String, dynamic>>();

    JavaScriptBackend backend = compiler.backend;

    for (OutputUnit outputUnit in
        infoCollector.mapper._outputUnit._elementToId.keys) {
      String id = infoCollector.mapper._outputUnit.add(outputUnit);
      outputUnits.add(<String, dynamic> {
        'id': id,
        'name': outputUnit.name,
        'size': backend.emitter.oldEmitter.outputBuffers[outputUnit].length,
      });
    }

    Map<String, dynamic> outJson = {
      'elements': infoCollector.toJson(),
      'holding': holding,
      'outputUnits': outputUnits,
      'dump_version': 3,
      'deferredFiles': compiler.deferredLoadTask.computeDeferredMap(),
      // This increases when new information is added to the map, but the viewer
      // still is compatible.
      'dump_minor_version': '1'
    };

    Duration toJsonDuration = new DateTime.now().difference(startToJsonTime);

    Map<String, dynamic> generalProgramInfo = <String, dynamic> {
      'size': _programSize,
      'dart2jsVersion': infoCollector.dart2jsVersion,
      'compilationMoment': new DateTime.now().toString(),
      'compilationDuration': compiler.totalCompileTime.elapsed.toString(),
      'toJsonDuration': 0,
      'dumpInfoDuration': this.timing.toString(),
      'noSuchMethodEnabled': compiler.enabledNoSuchMethod
    };

    outJson['program'] = generalProgramInfo;

    ChunkedConversionSink<Object> sink =
      encoder.startChunkedConversion(
          new StringConversionSink.fromStringSink(buffer));
    sink.add(outJson);
    compiler.reportInfo(NO_LOCATION_SPANNABLE,
        const MessageKind(
            "View the dumped .info.json file at "
            "https://dart-lang.github.io/dump-info-visualizer"));
  }
}
