// 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(div("+$describe", cls: "container"));
      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(describe);
    }
  }
}

/// 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(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(div('${span("Inferred " + description, cls: "kind")} '
                     '${span(esc(name),
                     cls: "name")} '
        '${span(esc(type), cls: 'type')} '));
  }
}

/// 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());
  }

  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;}
         div.contained {margin-left: 20px;}
         div {margin-top:0px;
         margin-bottom: 0px;
         white-space: pre; /*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>""");
  }
}
