// 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 'elements/elements.dart';
import 'elements/visitor.dart';
import 'dart:convert' show HtmlEscape;
import 'dart2jslib.dart' show
    Compiler,
    CompilerTask,
    CodeBuffer;
import 'dart_types.dart' show DartType;
import 'types/types.dart' show TypeMask;

// TODO (sigurdm): A search function.
// TODO (sigurdm): Output size of classes.
// TODO (sigurdm): Print that we dumped the HTML-file.
// TODO (sigurdm): Include why a given element was included in the output.
// TODO (sigurdm): Include how much output grew because of mirror support.
// TODO (sigurdm): Write each function with parameter names.
// TODO (sigurdm): Write how much space the boilerplate takes.
// TODO (sigurdm): Include javascript names of entities in the output.

class CodeSizeCounter {
  final Map<Element, int> generatedSize = new Map<Element, int>();

  int getGeneratedSizeOf(Element element) {
    int result = generatedSize[element];
    return result == null ? 0 : result;
  }

  void countCode(Element element, int added) {
    int before = generatedSize.putIfAbsent(element, () => 0);
    generatedSize[element] = before + added;
  }
}

tag(String element) {
  return (String content, {String cls}) {
    String classString = cls == null ? '' : ' class="$cls"';
    return '<$element$classString>$content</$element>';
  };
}

var div = tag('div');
var span = tag('span');
var code = tag('code');
var h2 = tag('h2');

var esc = const HtmlEscape().convert;

String sizeDescription(int size, ProgramInfo programInfo) {
  return size == null
      ? ''
      : span('${size} bytes '
        '(${size * 100 ~/ programInfo.size}%)', cls: "size");
}

/// An [InfoNode] holds information about a part the program.
abstract class InfoNode {
  String get name;

  int get size;

  void emitHtml(ProgramInfo programInfo, StringSink buffer);
}

/// An [ElementNode] holds information about an [Element]
class ElementInfoNode implements InfoNode {
  /// The name of the represented [Element].
  final String name;

  /// The kind of the [Element] represented.  This is presented to the
  /// user, so it might be more specific than [element.kind].
  final String kind;

  /// The static type of the represented [Element].
  /// [:null:] if this kind of element has no type.
  final String type;

  /// Any extra information to display about the represented [Element].
  final String extra;

  /// A textual description of the modifiers (such as "static", "abstract") of
  /// the represented [Element].
  final String modifiers;

  /// Describes how many bytes the code for the represented [Element] takes up
  /// in the output.
  final int size;

  /// Subnodes containing more detailed information about the represented
  /// [Element], and its members.
  List<InfoNode> contents;

  ElementInfoNode({this.name: "",
      this.kind: "",
      this.type,
      this.modifiers: "",
      this.size,
      this.contents,
      this.extra: ""});

  void emitHtml(ProgramInfo programInfo, StringSink buffer) {
    String kindString = span(esc(kind), cls: 'kind');
    String modifiersString = span(esc(modifiers), cls: "modifiers");

    String nameString = span(esc(name), cls: 'name');
    String typeString = type == null
        ? ''
        : span('/* ' + esc(type) + ' */', cls: 'type');
    String extraString = span(esc(extra), cls: 'type');
    String describe = [
        kindString,
        typeString,
        modifiersString,
        nameString,
        sizeDescription(size, programInfo),
        extraString].join(' ');

    if (contents != null) {
      buffer.write('\n');
      buffer.write(div("+$describe", cls: "container"));
      buffer.write('\n');
      buffer.write('<div class="contained">');
      if (contents.isEmpty) {
        buffer.writeln("No members");
      }
      for (InfoNode subElementDescription in contents) {
        subElementDescription.emitHtml(programInfo, buffer);
      }
      buffer.write("</div>");
    } else {
      buffer.writeln(div('$describe', cls: "element"));
    }
  }
}

/// A [CodeInfoNode] holds information about a piece of code.
class CodeInfoNode implements InfoNode {
  /// A short description of the code.
  final String description;

  final String generatedCode;

  get size => generatedCode.length;

  get name => "";

  CodeInfoNode({this.description: "", this.generatedCode});

  void emitHtml(ProgramInfo programInfo, StringBuffer buffer) {
    buffer.write('\n');
    buffer.write(div(description + ' ' +
                     sizeDescription(generatedCode.length, programInfo),
                     cls: 'kind') +
        code(esc(generatedCode)));
  }
}

/// Instances represent information inferred about the program such as
/// inferred type information or inferred side effects.
class InferredInfoNode implements InfoNode {
  /// Text describing the represented information.
  final String description;

  /// The name of the entity this information is inferred about (for example the
  /// name of a parameter).
  final String name;

  /// The inferred type/side effect.
  final String type;

  get size => 0;

  InferredInfoNode({this.name: "", this.description, this.type});

  void emitHtml(ProgramInfo programInfo, StringSink buffer) {
    buffer.write('\n');
    buffer.write(
        div('${span("Inferred " + description, cls: "kind")} '
            '${span(esc(name), cls: "name")} '
            '${span(esc(type), cls: "type")} ',
            cls: "attr"));
  }
}

/// Instances represent information about a program.
class ProgramInfo {
  /// A list of all the libraries in the program to show information about.
  final List<InfoNode> libraries;

  /// The size of the whole program in bytes.
  final int size;

  /// The time the compilation took place.
  final DateTime compilationMoment;

  /// The time the compilation took to complete.
  final Duration compilationDuration;

  /// The version of dart2js used to compile the program.
  final String dart2jsVersion;

  ProgramInfo({this.libraries,
               this.size,
               this.compilationMoment,
               this.compilationDuration,
               this.dart2jsVersion});
}

class InfoDumpVisitor extends ElementVisitor<InfoNode> {
  final Compiler compiler;

  /// Contains the elements visited on the path from the library to here.
  List<Element> stack = new List<Element>();

  Element get currentElement => stack.last;

  InfoDumpVisitor(Compiler this.compiler);

  InfoNode visitElement(Element element) {
    compiler.internalError("This element of kind ${element.kind} "
        "does not support --dump-info",
        token: element.position());
    return null;
  }

  InfoNode visitLibraryElement(LibraryElement element) {
    List<InfoNode> contents = new List<InfoNode>();
    int size = compiler.dumpInfoTask.codeSizeCounter
        .getGeneratedSizeOf(element);
    if (size == 0) return null;
    stack.add(element);
    element.forEachLocalMember((Element member) {
      InfoNode info = member.accept(this);
      if (info != null) {
        contents.add(info);
      }
    });
    stack.removeLast();
    String nameString = element.getLibraryName() == ""
        ? "<unnamed>"
        : element.getLibraryName();
    contents.sort((InfoNode e1, InfoNode e2) {
      return e1.name.compareTo(e2.name);
    });
    return new ElementInfoNode(
        extra: "${element.canonicalUri}",
        kind: "library",
        name: nameString,
        size: size,
        modifiers: "",
        contents: contents);
  }

  InfoNode visitTypedefElement(TypedefElement element) {
    return element.alias == null
        ? null
        : new ElementInfoNode(
            type: element.alias.toString(),
            kind: "typedef",
            name: element.name);
  }

  InfoNode visitFieldElement(FieldElement element) {
    CodeBuffer emittedCode = compiler.backend.codeOf(element);
    int size = 0;
    DartType type = element.computeType(compiler);
    TypeMask inferredType = compiler.typesTask
        .getGuaranteedTypeOfElement(element);
    // If a field has an empty inferred type it is never used.
    if ((inferredType == null || inferredType.isEmpty) && emittedCode == null) {
      return null;
    }
    List<InfoNode> contents = new List<InfoNode>();
    if (emittedCode != null) {
      contents.add(new CodeInfoNode(
          description: "Generated initializer",
          generatedCode: emittedCode.getText()));
      size = emittedCode.length;
    }
    if (inferredType != null) {
      contents.add(new InferredInfoNode(
          description: "type",
          type: inferredType.toString()));
      stack.add(element);
    }
    for (Element closure in element.nestedClosures) {
      InfoNode info = closure.accept(this);
      if (info != null) {
        contents.add(info);
        size += info.size;
      }
    }
    stack.removeLast();

    return new ElementInfoNode(
        kind: "field",
        type: "$type",
        name: element.name,
        size: size,
        modifiers: "${element.modifiers}",
        contents: contents);
  }

  InfoNode visitClassElement(ClassElement element) {
    // If the element is not resolved it is not used in the program, and we omit
    // it from the output.
    if (!element.isResolved) return null;
    String modifiersString = "${element.modifiers}";
    String supersString = element.allSupertypes == null ? "" :
        "implements ${element.allSupertypes}";
    List contents = [];
    stack.add(element);
    element.forEachLocalMember((Element member) {
      InfoNode info = member.accept(this);
      if (info != null) {
        contents.add(info);
      }
    });
    stack.removeLast();
    if (contents.isEmpty) {
      // TODO (sigurdm): Only return here if the class is never used in type
      // checks.
      return null;
    }
    contents.sort((InfoNode n1, InfoNode n2) {
      return n1.name.compareTo(n2.name);
    });
    return new ElementInfoNode(
        kind: "class",
        name: element.name,
        extra: supersString,
        modifiers: modifiersString,
        contents: contents);
  }

  InfoNode visitFunctionElement(FunctionElement element) {
    CodeBuffer emittedCode = compiler.backend.codeOf(element);
    int size = 0;
    String nameString = element.name;
    String modifiersString = "${element.modifiers}";
    String kindString = "function";
    if (currentElement.isClass()) {
      kindString = "method";
    } else if (currentElement.isField() ||
               currentElement.isFunction() ||
               currentElement.isConstructor()) {
      kindString = "closure";
      nameString = "<unnamed>";
    }
    if (element.isConstructor()) {
      nameString = element.name == ""
          ? "${element.enclosingElement.name}"
          : "${element.enclosingElement.name}.${element.name}";
      kindString = "constructor";
    }
    List contents = [];
    if (emittedCode != null) {
      FunctionSignature signature = element.computeSignature(compiler);
      signature.forEachParameter((parameter) {
        contents.add(new InferredInfoNode(
            description: "parameter",
            name: parameter.name,
            type: compiler.typesTask
              .getGuaranteedTypeOfElement(parameter).toString()));
      });
      contents.add(new InferredInfoNode(
          description: "return type",
          type: compiler.typesTask
            .getGuaranteedReturnTypeOfElement(element).toString()));
      contents.add(new InferredInfoNode(
        description: "side effects",
        type: compiler.world
            .getSideEffectsOfElement(element).toString()));
      contents.add(new CodeInfoNode(
          description: "Generated code",
          generatedCode: emittedCode.getText()));
      size += emittedCode.length;
    }
    stack.add(element);
    for (Element closure in element.nestedClosures) {
      InfoNode info = closure.accept(this);
      if (info != null) {
        contents.add(info);
        size += info.size;
      }
    }
    stack.removeLast();
    if (size == 0) {
      return null;
    }
    return new ElementInfoNode(
        type: element.type.toString(),
        kind: kindString,
        name: nameString,
        size: size,
        modifiers: modifiersString,
        contents: contents);
  }
}

class DumpInfoTask extends CompilerTask {
  DumpInfoTask(Compiler compiler)
      : infoDumpVisitor = new InfoDumpVisitor(compiler),
        super(compiler);

  String name = "Dump Info";

  final CodeSizeCounter codeSizeCounter = new CodeSizeCounter();

  final InfoDumpVisitor infoDumpVisitor;

  void dumpInfo() {
    measure(() {
      ProgramInfo info = collectDumpInfo();
      StringBuffer buffer = new StringBuffer();
      dumpInfoHtml(info, buffer);
      compiler.outputProvider('', 'info.html')
        ..add(buffer.toString())
        ..close();
    });
  }

  ProgramInfo collectDumpInfo() {
    List<LibraryElement> sortedLibraries = compiler.libraries.values.toList();
    sortedLibraries.sort((LibraryElement l1, LibraryElement l2) {
      if (l1.isPlatformLibrary && !l2.isPlatformLibrary) {
        return 1;
      } else if (!l1.isPlatformLibrary && l2.isPlatformLibrary) {
        return -1;
      }
      return l1.getLibraryName().compareTo(l2.getLibraryName());
    });

    List<InfoNode> libraryInfos = new List<InfoNode>();
    libraryInfos.addAll(sortedLibraries
        .map((library) => infoDumpVisitor.visit(library))
        .where((info) => info != null));

    return new ProgramInfo(
        compilationDuration: compiler.totalCompileTime.elapsed,
        // TODO (sigurdm): Also count the size of deferred code
        size: compiler.assembledCode.length,
        libraries: libraryInfos,
        compilationMoment: new DateTime.now(),
        dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null);
  }

  void dumpInfoHtml(ProgramInfo info, StringSink buffer) {
    int totalSize = info.size;

    buffer.writeln("""
<html>
  <head>
    <title>Dart2JS compilation information</title>
       <style>
         code {margin-left: 20px; display: block; white-space: pre; }
         div.container, div.contained, div.element, div.attr {
           margin-top:0px;
           margin-bottom: 0px;
         }
         div.container, div.element, div.attr {
           white-space: pre;
         }
         div.contained {margin-left: 20px;}
         div {/*border: 1px solid;*/}
         span.kind {}
         span.modifiers {font-weight:bold;}
         span.name {font-weight:bold; font-family: monospace;}
         span.type {font-family: monospace; color:blue;}
       </style>
     </head>
     <body>
       <h1>Dart2js compilation information</h1>""");
    buffer.writeln(h2('Compilation took place: '
                      '${info.compilationMoment}'));
    buffer.writeln(h2('Compilation took: '
                      '${info.compilationDuration.inSeconds} seconds'));
    buffer.writeln(h2('Output size: ${info.size} bytes'));
    if (info.dart2jsVersion != null) {
      buffer.writeln(h2('Dart2js version: ${info.dart2jsVersion}'));
    }

    info.libraries.forEach((InfoNode node) {
      node.emitHtml(info, buffer);
    });


    // TODO (sigurdm): This script should be written in dart
    buffer.writeln(r"""
    <script type="text/javascript">
      function toggler(element) {
        return function(e) {
          element.hidden = !element.hidden;
        };
      }
      var containers = document.getElementsByClassName('container');
      for (var i = 0; i < containers.length; i++) {
        var container = containers[i];
        container.addEventListener('click',
          toggler(container.nextElementSibling), false);
       container.nextElementSibling.hidden = true;
      };
    </script>
  </body>
</html>""");
  }
}
