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

import 'dart:async';
import 'dart:html';
import 'dart:math';
import 'observatory_element.dart';
import 'service_ref.dart';
import 'package:observatory/service.dart';
import 'package:observatory/utils.dart';
import 'package:polymer/polymer.dart';
import 'package:logging/logging.dart';

const nbsp = "\u00A0";

void addInfoBox(Element content, Function infoBoxGenerator) {
  var infoBox;
  var show = false;
  var originalBackground = content.style.backgroundColor;
  buildInfoBox() {
    infoBox = infoBoxGenerator();
    infoBox.style.position = 'absolute';
    infoBox.style.padding = '1em';
    infoBox.style.border = 'solid black 2px';
    infoBox.style.zIndex = '10';
    infoBox.style.backgroundColor = 'white';
    infoBox.style.cursor = 'auto';
    // Don't inherit pre formating from the script lines.
    infoBox.style.whiteSpace = 'normal';
    content.append(infoBox);
  }
  content.onClick.listen((event) {
    show = !show;
    if (infoBox == null) buildInfoBox();  // Created lazily on the first click.
    infoBox.style.display = show ? 'block' : 'none';
    content.style.backgroundColor = show ? 'white' : originalBackground;
  });

  // Causes infoBox to be positioned relative to the bottom-left of content.
  content.style.display = 'inline-block';
  content.style.cursor = 'pointer';
}


void addLink(Element content, String target) {
  // Ick, destructive but still compatible with also adding an info box.
  var a = new AnchorElement(href: target);
  a.text = content.text;
  content.text = '';
  content.append(a);
}


abstract class Annotation implements Comparable<Annotation> {
  int line;
  int columnStart;
  int columnStop;
  int get priority;

  void applyStyleTo(element);

  int compareTo(Annotation other) {
    if (line == other.line) {
      if (columnStart == other.columnStart) {
        return priority.compareTo(other.priority);
      }
      return columnStart.compareTo(other.columnStart);
    }
    return line.compareTo(other.line);
  }

  Element table() {
    var e = new DivElement();
    e.style.display = "table";
    e.style.color = "#333";
    e.style.font = "400 14px 'Montserrat', sans-serif";
    return e;
  }

  Element row([content]) {
    var e = new DivElement();
    e.style.display = "table-row";
    if (content is String) e.text = content;
    if (content is Element) e.children.add(content);
    return e;
  }

  Element cell(content) {
    var e = new DivElement();
    e.style.display = "table-cell";
    e.style.padding = "3px";
    if (content is String) e.text = content;
    if (content is Element) e.children.add(content);
    return e;
  }

  Element serviceRef(object) {
    AnyServiceRefElement e = new Element.tag("any-service-ref");
    e.ref = object;
    return e;
  }
}

class CurrentExecutionAnnotation extends Annotation {
  int priority = 0;  // highest priority.

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.classes.add("currentCol");
    element.title = "Current execution";
  }
}

class BreakpointAnnotation extends Annotation {
  Breakpoint bpt;
  int priority = 1;

  BreakpointAnnotation(this.bpt) {
    var script = bpt.location.script;
    var location = bpt.location;
    if (location.tokenPos != null) {
      var pos = location.tokenPos;
      line = script.tokenToLine(pos);
      columnStart = script.tokenToCol(pos) - 1;  // tokenToCol is 1-origin.
    } else if (location is UnresolvedSourceLocation) {
      line = location.line;
      columnStart = location.column;
      if (columnStart == null) {
        columnStart = 0;
      }
    }
    var length = script.guessTokenLength(line, columnStart);
    if (length == null) {
      length = 1;
    }
    columnStop = columnStart + length;
  }

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    var script = bpt.location.script;
    var pos = bpt.location.tokenPos;
    int line = script.tokenToLine(pos);
    int column = script.tokenToCol(pos);
    if (bpt.resolved) {
      element.classes.add("resolvedBreakAnnotation");
    } else {
      element.classes.add("unresolvedBreakAnnotation");
    }
    element.title = "Breakpoint ${bpt.number} at ${line}:${column}";
  }
}

class LibraryAnnotation extends Annotation {
  Library target;
  String url;
  int priority = 2;

  LibraryAnnotation(this.target, this.url);

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.title = "library ${target.uri}";
    addLink(element, url);
  }
}

class PartAnnotation extends Annotation {
  Script part;
  String url;
  int priority = 2;

  PartAnnotation(this.part, this.url);

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.title = "script ${part.uri}";
    addLink(element, url);
  }
}

class LocalVariableAnnotation extends Annotation {
  final value;
  int priority = 2;

  LocalVariableAnnotation(LocalVarLocation location, this.value) {
    line = location.line;
    columnStart = location.column;
    columnStop = location.endColumn;
  }

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.style.fontWeight = "bold";
    element.title = "${value.shortName}";
  }
}

class CallSiteAnnotation extends Annotation {
  CallSite callSite;
  int priority = 2;

  CallSiteAnnotation(this.callSite) {
    line = callSite.line;
    columnStart = callSite.column - 1;  // Call site is 1-origin.
    var tokenLength = callSite.script.guessTokenLength(line, columnStart);
    if (tokenLength == null) {
      tokenLength = callSite.name.length;  // Approximate.
      if (callSite.name.startsWith("get:") ||
          callSite.name.startsWith("set:")) tokenLength -= 4;
    }
    columnStop = columnStart + tokenLength;
  }

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.style.fontWeight = "bold";
    element.title = "Call site: ${callSite.name}";

    addInfoBox(element, () {
      var details = table();
      if (callSite.entries.isEmpty) {
        details.append(row('Call of "${callSite.name}" did not execute'));
      } else {
        var r = row();
        r.append(cell("Container"));
        r.append(cell("Count"));
        r.append(cell("Target"));
        details.append(r);

        for (var entry in callSite.entries) {
          var r = row();
          r.append(cell(serviceRef(entry.receiver)));
          r.append(cell(entry.count.toString()));
          r.append(cell(serviceRef(entry.target)));
          details.append(r);
        }
      }
      return details;
    });
  }
}

abstract class DeclarationAnnotation extends Annotation {
  String url;
  int priority = 2;

  DeclarationAnnotation(decl, this.url) {
    assert(decl.loaded);
    SourceLocation location = decl.location;
    if (location == null) {
      line = 0;
      columnStart = 0;
      columnStop = 0;
      return;
    }

    Script script = location.script;
    line = script.tokenToLine(location.tokenPos);
    columnStart = script.tokenToCol(location.tokenPos);
    if ((line == null) || (columnStart == null)) {
      line = 0;
      columnStart = 0;
      columnStop = 0;
    } else {
      columnStart--; // 1-origin -> 0-origin.

      // The method's token position is at the beginning of the method
      // declaration, which may be a return type annotation, metadata, static
      // modifier, etc. Try to scan forward to position this annotation on the
      // function's name instead.
      var lineSource = script.getLine(line).text;
      var betterStart = lineSource.indexOf(decl.name, columnStart);
      if (betterStart != -1) {
        columnStart = betterStart;
      }
      columnStop = columnStart + decl.name.length;
    }
  }
}

class ClassDeclarationAnnotation extends DeclarationAnnotation {
  Class klass;

  ClassDeclarationAnnotation(Class cls, String url)
    : klass = cls,
      super(cls, url);

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    element.title = "class ${klass.name}";
    addLink(element, url);
  }
}

class FieldDeclarationAnnotation extends DeclarationAnnotation {
  Field field;

  FieldDeclarationAnnotation(Field fld, String url)
    : field = fld,
      super(fld, url);

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    var tooltip = "field ${field.name}";
    element.title = tooltip;
    addLink(element, url);
  }
}

class FunctionDeclarationAnnotation extends DeclarationAnnotation {
  ServiceFunction function;

  FunctionDeclarationAnnotation(ServiceFunction func, String url)
    : function = func,
      super(func, url);

  void applyStyleTo(element) {
    if (element == null) {
      return;  // TODO(rmacnak): Handling overlapping annotations.
    }
    var tooltip = "method ${function.name}";
    if (function.isOptimizable == false) {
      tooltip += "\nUnoptimizable!";
    }
    if (function.isInlinable == false) {
      tooltip += "\nNot inlinable!";
    }
    if (function.deoptimizations > 0) {
      tooltip += "\nDeoptimized ${function.deoptimizations} times!";
    }
    element.title = tooltip;

    if (function.isOptimizable == false ||
        function.isInlinable == false ||
        function.deoptimizations >0) {
      element.style.backgroundColor = "#EEA7A7";  // Low-saturation red.
    }

    addLink(element, url);
  }
}

class ScriptLineProfile {
  ScriptLineProfile(this.line, this.sampleCount);

  static const kHotThreshold = 0.05;  // 5%.
  static const kMediumThreshold = 0.02;  // 2%.

  final int line;
  final int sampleCount;

  int selfTicks = 0;
  int totalTicks = 0;

  void process(int exclusive, int inclusive) {
    selfTicks += exclusive;
    totalTicks += inclusive;
  }

  String get formattedSelfTicks {
    return Utils.formatPercent(selfTicks, sampleCount);
  }

  String get formattedTotalTicks {
    return Utils.formatPercent(totalTicks, sampleCount);
  }

  double _percent(bool self) {
    if (sampleCount == 0) {
      return 0.0;
    }
    if (self) {
      return selfTicks / sampleCount;
    } else {
      return totalTicks / sampleCount;
    }
  }

  bool isHot(bool self) => _percent(self) > kHotThreshold;
  bool isMedium(bool self) => _percent(self) > kMediumThreshold;
}

/// Box with script source code in it.
@CustomTag('script-inset')
class ScriptInsetElement extends ObservatoryElement {
  @published Script script;
  @published int startPos;
  @published int endPos;

  /// Set the height to make the script inset scroll.  Otherwise it
  /// will show from startPos to endPos.
  @published String height = null;

  @published int currentPos;
  @published bool inDebuggerContext = false;
  @published ObservableList variables;

  @published Element scroller;
  RefreshButtonElement _refreshButton;
  ToggleButtonElement _toggleProfileButton;

  int _currentLine;
  int _currentCol;
  int _startLine;
  int _endLine;

  Map<int, List<ServiceMap>> _rangeMap = {};
  Set _callSites = new Set<CallSite>();
  Set _possibleBreakpointLines = new Set<int>();
  Map<int, ScriptLineProfile> _profileMap = {};

  var annotations = [];
  var annotationsCursor;

  StreamSubscription _scriptChangeSubscription;
  Future<StreamSubscription> _debugSubscriptionFuture;
  StreamSubscription _scrollSubscription;

  bool hasLoadedLibraryDeclarations = false;
  bool _includeProfile = false;

  String makeLineId(int line) {
    return 'line-$line';
  }

  void _scrollToCurrentPos() {
    var line = shadowRoot.getElementById(makeLineId(_currentLine));
    if (line != null) {
      line.scrollIntoView();
    }
  }

  void attached() {
    super.attached();
    _debugSubscriptionFuture =
        app.vm.listenEventStream(VM.kDebugStream, _onDebugEvent);
    if (scroller != null) {
      _scrollSubscription = scroller.onScroll.listen(_onScroll);
    } else {
      _scrollSubscription = window.onScroll.listen(_onScroll);
    }
  }

  void detached() {
    cancelFutureSubscription(_debugSubscriptionFuture);
    _debugSubscriptionFuture = null;
    if (_scrollSubscription != null) {
      _scrollSubscription.cancel();
      _scrollSubscription = null;
    }
    if (_scriptChangeSubscription != null) {
      // Don't leak. If only Dart and Javascript exposed weak references...
      _scriptChangeSubscription.cancel();
      _scriptChangeSubscription = null;
    }
    super.detached();
  }

  void _onScroll(event) {
    if (_refreshButton != null) {
      var newTop = _buttonTop(_refreshButton);
      if (_refreshButton.style.top != newTop) {
        _refreshButton.style.top = '${newTop}px';
      }
    }
    if (_toggleProfileButton != null) {
      var newTop = _buttonTop(_toggleProfileButton);
      if (_toggleProfileButton.style.top != newTop) {
        _toggleProfileButton.style.top = '${newTop}px';
      }
    }
  }

  void _onDebugEvent(event) {
    if (script == null) {
      return;
    }
    switch (event.kind) {
      case ServiceEvent.kBreakpointAdded:
      case ServiceEvent.kBreakpointResolved:
      case ServiceEvent.kBreakpointRemoved:
        var loc = event.breakpoint.location;
        if (loc.script == script) {
          int line;
          if (loc.tokenPos != null) {
            line = script.tokenToLine(loc.tokenPos);
          } else {
            line = loc.line;
          }
          if ((line >= _startLine) && (line <= _endLine)) {
            _updateTask.queue();
          }
        }
        break;
      default:
        // Ignore.
        break;
    }
  }

  void currentPosChanged(oldValue) {
    _updateTask.queue();
    _scrollToCurrentPos();
  }

  void startPosChanged(oldValue) {
    _updateTask.queue();
  }

  void endPosChanged(oldValue) {
    _updateTask.queue();
  }

  void scriptChanged(oldValue) {
    _updateTask.queue();
  }

  void variablesChanged(oldValue) {
    _updateTask.queue();
  }

  Element a(String text) => new AnchorElement()..text = text;
  Element span(String text) => new SpanElement()..text = text;

  Element hitsCurrent(Element element) {
    element.classes.add('hitsCurrent');
    element.title = "";
    return element;
  }
  Element hitsUnknown(Element element) {
    element.classes.add('hitsNone');
    element.title = "";
    return element;
  }
  Element hitsNotExecuted(Element element) {
    element.classes.add('hitsNotExecuted');
    element.title = "Line did not execute";
    return element;
  }
  Element hitsExecuted(Element element) {
    element.classes.add('hitsExecuted');
    element.title = "Line did execute";
    return element;
  }
  Element hitsCompiled(Element element) {
    element.classes.add('hitsCompiled');
    element.title = "Line in compiled function";
    return element;
  }
  Element hitsNotCompiled(Element element) {
    element.classes.add('hitsNotCompiled');
    element.title = "Line in uncompiled function";
    return element;
  }

  Element container;

  Future _refresh() async {
    await update();
  }

  // Build _rangeMap and _callSites from a source report.
  Future _refreshSourceReport() async {
    var reports = [Isolate.kCallSitesReport,
                   Isolate.kPossibleBreakpointsReport];
    if (_includeProfile) {
      reports.add(Isolate.kProfileReport);
    }
    var sourceReport = await script.isolate.getSourceReport(
        reports,
        script, startPos, endPos);
    _possibleBreakpointLines = getPossibleBreakpointLines(sourceReport, script);
    _rangeMap.clear();
    _callSites.clear();
    _profileMap.clear();
    for (var range in sourceReport['ranges']) {
      int startLine = script.tokenToLine(range['startPos']);
      int endLine = script.tokenToLine(range['endPos']);
      // TODO(turnidge): Track down the root cause of null startLine/endLine.
      if ((startLine != null) && (endLine != null)) {
        for (var line = startLine; line <= endLine; line++) {
          var rangeList = _rangeMap[line];
          if (rangeList == null) {
            _rangeMap[line] = [range];
          } else {
            rangeList.add(range);
          }
        }
      }
      if (_includeProfile && range['profile'] != null) {
        List positions = range['profile']['positions'];
        List exclusiveTicks = range['profile']['exclusiveTicks'];
        List inclusiveTicks = range['profile']['inclusiveTicks'];
        int sampleCount = range['profile']['metadata']['sampleCount'];
        assert(positions.length == exclusiveTicks.length);
        assert(positions.length == inclusiveTicks.length);
        for (int i = 0; i < positions.length; i++) {
          if (positions[i] is String) {
            // String positions are classifying token positions.
            // TODO(johnmccutchan): Add classifier data to UI.
            continue;
          }
          int line = script.tokenToLine(positions[i]);
          ScriptLineProfile lineProfile = _profileMap[line];
          if (lineProfile == null) {
            lineProfile = new ScriptLineProfile(line, sampleCount);
            _profileMap[line] = lineProfile;
          }
          lineProfile.process(exclusiveTicks[i], inclusiveTicks[i]);
        }
      }
      if (range['compiled']) {
        var rangeCallSites = range['callSites'];
        if (rangeCallSites != null) {
          for (var callSiteMap in rangeCallSites) {
            _callSites.add(new CallSite.fromMap(callSiteMap, script));
          }
        }
      }
    }
  }

  Task _updateTask;
  Future update() async {
    assert(_updateTask != null);
    if (script == null) {
      // We may have previously had a script.
      if (container != null) {
        container.children.clear();
      }
      return;
    }
    if (!script.loaded) {
      await script.load();
    }
    if (_scriptChangeSubscription == null) {
      _scriptChangeSubscription = script.changes.listen((_) => update());
    }
    await _refreshSourceReport();

    computeAnnotations();

    var table = linesTable();
    var firstBuild = false;
    if (container == null) {
      // Indirect to avoid deleting the style element.
      container = new DivElement();
      shadowRoot.append(container);
      firstBuild = true;
    }
    container.children.clear();
    container.children.add(table);
    makeCssClassUncopyable(table, "noCopy");
    if (firstBuild) {
      _scrollToCurrentPos();
    }
  }

  void computeAnnotations() {
    _startLine = (startPos != null
                  ? script.tokenToLine(startPos)
                  : 1 + script.lineOffset);
    _currentLine = (currentPos != null
                    ? script.tokenToLine(currentPos)
                    : null);
    _currentCol = (currentPos != null
                   ? (script.tokenToCol(currentPos))
                   : null);
    if (_currentCol != null) {
      _currentCol--;  // make this 0-based.
    }

    _endLine = (endPos != null
                ? script.tokenToLine(endPos)
                : script.lines.length + script.lineOffset);

    if (_startLine == null || _endLine == null) {
      return;
    }

    annotations.clear();

    addCurrentExecutionAnnotation();
    addBreakpointAnnotations();

    if (!inDebuggerContext && script.library != null) {
      if (hasLoadedLibraryDeclarations) {
        addLibraryAnnotations();
        addDependencyAnnotations();
        addPartAnnotations();
        addClassAnnotations();
        addFieldAnnotations();
        addFunctionAnnotations();
        addCallSiteAnnotations();
      } else {
        loadDeclarationsOfLibrary(script.library).then((_) {
          hasLoadedLibraryDeclarations = true;
          update();
        });
      }
    }

    addLocalVariableAnnotations();

    annotations.sort();
  }

  void addCurrentExecutionAnnotation() {
    if (_currentLine != null) {
      var a = new CurrentExecutionAnnotation();
      a.line = _currentLine;
      a.columnStart = _currentCol;
      var length = script.guessTokenLength(_currentLine, _currentCol);
      if (length == null) {
        length = 1;
      }
      a.columnStop = _currentCol + length;
      annotations.add(a);
    }
  }

  void addBreakpointAnnotations() {
    for (var line = _startLine; line <= _endLine; line++) {
      var bpts = script.getLine(line).breakpoints;
      if (bpts != null) {
        for (var bpt in bpts) {
          if (bpt.location != null) {
            annotations.add(new BreakpointAnnotation(bpt));
          }
        }
      }
    }
  }

  Future loadDeclarationsOfLibrary(Library lib) {
    return lib.load().then((lib) {
      var loads = [];
      for (var func in lib.functions) {
        loads.add(func.load());
      }
      for (var field in lib.variables) {
        loads.add(field.load());
      }
      for (var cls in lib.classes) {
        loads.add(loadDeclarationsOfClass(cls));
      }
      return Future.wait(loads);
    });
  }

  Future loadDeclarationsOfClass(Class cls) {
    return cls.load().then((cls) {
      var loads = [];
      for (var func in cls.functions) {
        loads.add(func.load());
      }
      for (var field in cls.fields) {
        loads.add(field.load());
      }
      return Future.wait(loads);
    });
  }

  String inspectLink(ServiceObject ref) {
    return gotoLink('/inspect', ref);
  }

  void addLibraryAnnotations() {
    for (ScriptLine line in script.lines) {
      // TODO(rmacnak): Use a real scanner.
      var pattern = new RegExp("library ${script.library.name}");
      var match = pattern.firstMatch(line.text);
      if (match != null) {
        var anno = new LibraryAnnotation(script.library,
                                         inspectLink(script.library));
        anno.line = line.line;
        anno.columnStart = match.start + 8;
        anno.columnStop = match.end;
        annotations.add(anno);
      }
      // TODO(rmacnak): Use a real scanner.
      pattern = new RegExp("part of ${script.library.name}");
      match = pattern.firstMatch(line.text);
      if (match != null) {
        var anno = new LibraryAnnotation(script.library,
                                         inspectLink(script.library));
        anno.line = line.line;
        anno.columnStart = match.start + 8;
        anno.columnStop = match.end;
        annotations.add(anno);
      }
    }
  }

  Library resolveDependency(String relativeUri) {
    // This isn't really correct: we need to ask the embedder to do the
    // uri canonicalization for us, but Observatory isn't in a position
    // to invoke the library tag handler. Handle the most common cases.
    var targetUri = Uri.parse(script.library.uri).resolve(relativeUri);
    for (Library l in script.isolate.libraries) {
      if (targetUri.toString() == l.uri) {
        return l;
      }
    }
    if (targetUri.scheme == 'package') {
      targetUri = "packages/${targetUri.path}";
      for (Library l in script.isolate.libraries) {
        if (targetUri.toString() == l.uri) {
          return l;
        }
      }
    }

    Logger.root.info("Could not resolve library dependency: $relativeUri");
    return null;
  }

  void addDependencyAnnotations() {
    // TODO(rmacnak): Use a real scanner.
    var patterns = [
      new RegExp("import '(.*)'"),
      new RegExp('import "(.*)"'),
      new RegExp("export '(.*)'"),
      new RegExp('export "(.*)"'),
    ];
    for (ScriptLine line in script.lines) {
      for (var pattern in patterns) {
        var match = pattern.firstMatch(line.text);
        if (match != null) {
          Library target = resolveDependency(match[1]);
          if (target != null) {
            var anno = new LibraryAnnotation(target, inspectLink(target));
            anno.line = line.line;
            anno.columnStart = match.start + 8;
            anno.columnStop = match.end - 1;
            annotations.add(anno);
          }
        }
      }
    }
  }

  Script resolvePart(String relativeUri) {
    var rootUri = Uri.parse(script.library.uri);
    if (rootUri.scheme == 'dart') {
      // The relative paths from dart:* libraries to their parts are not valid.
      rootUri = new Uri.directory(script.library.uri);
    }
    var targetUri = rootUri.resolve(relativeUri);
    for (Script s in script.library.scripts) {
      if (targetUri.toString() == s.uri) {
        return s;
      }
    }
    Logger.root.info("Could not resolve part: $relativeUri");
    return null;
  }

  void addPartAnnotations() {
    // TODO(rmacnak): Use a real scanner.
    var patterns = [
      new RegExp("part '(.*)'"),
      new RegExp('part "(.*)"'),
    ];
    for (ScriptLine line in script.lines) {
      for (var pattern in patterns) {
        var match = pattern.firstMatch(line.text);
        if (match != null) {
          Script part = resolvePart(match[1]);
          if (part != null) {
            var anno = new PartAnnotation(part, inspectLink(part));
            anno.line = line.line;
            anno.columnStart = match.start + 6;
            anno.columnStop = match.end - 1;
            annotations.add(anno);
          }
        }
      }
    }
  }

  void addClassAnnotations() {
    for (var cls in script.library.classes) {
      if ((cls.location != null) && (cls.location.script == script)) {
        var a = new ClassDeclarationAnnotation(cls, inspectLink(cls));
        annotations.add(a);
      }
    }
  }

  void addFieldAnnotations() {
    for (var field in script.library.variables) {
      if ((field.location != null) && (field.location.script == script)) {
        var a = new FieldDeclarationAnnotation(field, inspectLink(field));
        annotations.add(a);
      }
    }
    for (var cls in script.library.classes) {
      for (var field in cls.fields) {
        if ((field.location != null) && (field.location.script == script)) {
          var a = new FieldDeclarationAnnotation(field, inspectLink(field));
          annotations.add(a);
        }
      }
    }
  }

  void addFunctionAnnotations() {
    for (var func in script.library.functions) {
      if ((func.location != null) &&
          (func.location.script == script) &&
          (func.kind != FunctionKind.kImplicitGetterFunction) &&
          (func.kind != FunctionKind.kImplicitSetterFunction)) {
        // We annotate a field declaration with the field instead of the
        // implicit getter or setter.
        var a = new FunctionDeclarationAnnotation(func, inspectLink(func));
        annotations.add(a);
      }
    }
    for (var cls in script.library.classes) {
      for (var func in cls.functions) {
        if ((func.location != null) &&
            (func.location.script == script) &&
            (func.kind != FunctionKind.kImplicitGetterFunction) &&
            (func.kind != FunctionKind.kImplicitSetterFunction)) {
          // We annotate a field declaration with the field instead of the
          // implicit getter or setter.
          var a = new FunctionDeclarationAnnotation(func, inspectLink(func));
          annotations.add(a);
        }
      }
    }
  }

  void addCallSiteAnnotations() {
    for (var callSite in _callSites) {
      annotations.add(new CallSiteAnnotation(callSite));
    }
  }

  void addLocalVariableAnnotations() {
    // We have local variable information.
    if (variables != null) {
      // For each variable.
      for (var variable in variables) {
        // Find variable usage locations.
        var locations = script.scanForLocalVariableLocations(
              variable['name'],
              variable['_tokenPos'],
              variable['_endTokenPos']);

        // Annotate locations.
        for (var location in locations) {
          annotations.add(new LocalVariableAnnotation(location,
                                                      variable['value']));
        }
      }
    }
  }

  int _buttonTop(Element element) {
    if (element == null) {
      return 5;
    }
    const padding = 5;
    // TODO (cbernaschina) check if this is needed.
    const navbarHeight = 40;
    var rect = getBoundingClientRect();
    var buttonHeight = element.clientHeight;
    return min(max(0, navbarHeight - rect.top) + padding,
               rect.height - (buttonHeight + padding));
  }

  RefreshButtonElement _newRefreshButton() {
    var button = new Element.tag('refresh-button');
    button.style.position = 'absolute';
    button.style.display = 'inline-block';
    button.style.top = '${_buttonTop(null)}px';
    button.style.right = '5px';
    button.callback = _refresh;
    button.title = 'Refresh coverage';
    return button;
  }

  ToggleButtonElement _newToggleProfileButton() {
    ToggleButtonElement button = new Element.tag('toggle-button');
    button.style.position = 'absolute';
    button.style.display = 'inline-block';
    button.style.top = '${_buttonTop(null)}px';
    button.style.right = '30px';
    button.title = 'Toggle CPU profile information';
    final String enabledColor = 'black';
    final String disabledColor = 'rgba(0, 0, 0 ,.3)';
    button.callback = (enabled) async {
      _includeProfile = enabled;
      if (button.children.length > 0) {
        var content = button.children[0];
        if (enabled) {
          content.style.color = enabledColor;
        } else {
          content.style.color = disabledColor;
        }
      }
      await update();
    };
    button.children.add(new Element.tag('icon-whatshot'));
    button.children[0].style.color = disabledColor;
    button.enabled = _includeProfile;
    return button;
  }

  Element linesTable() {
    var table = new DivElement();
    table.classes.add("sourceTable");

    _refreshButton = _newRefreshButton();
    _toggleProfileButton = _newToggleProfileButton();
    table.append(_refreshButton);
    table.append(_toggleProfileButton);

    if (_startLine == null || _endLine == null) {
      return table;
    }

    var endLine = (endPos != null
                   ? script.tokenToLine(endPos)
                   : script.lines.length + script.lineOffset);
    var lineNumPad = endLine.toString().length;

    annotationsCursor = 0;

    int blankLineCount = 0;
    for (int i = _startLine; i <= _endLine; i++) {
      var line = script.getLine(i);
      if (line.isBlank) {
        // Try to introduce elipses if there are 4 or more contiguous
        // blank lines.
        blankLineCount++;
      } else {
        if (blankLineCount > 0) {
          int firstBlank = i - blankLineCount;
          int lastBlank = i - 1;
          if (blankLineCount < 4) {
            // Too few blank lines for an elipsis.
            for (int j = firstBlank; j  <= lastBlank; j++) {
              table.append(lineElement(script.getLine(j), lineNumPad));
            }
          } else {
            // Add an elipsis for the skipped region.
            table.append(lineElement(script.getLine(firstBlank), lineNumPad));
            table.append(lineElement(null, lineNumPad));
            table.append(lineElement(script.getLine(lastBlank), lineNumPad));
          }
          blankLineCount = 0;
        }
        table.append(lineElement(line, lineNumPad));
      }
    }

    return table;
  }

  // Assumes annotations are sorted.
  Annotation nextAnnotationOnLine(int line) {
    if (annotationsCursor >= annotations.length) return null;
    var annotation = annotations[annotationsCursor];

    // Fast-forward past any annotations before the first line that
    // we are displaying.
    while (annotation.line < line) {
      annotationsCursor++;
      if (annotationsCursor >= annotations.length) return null;
      annotation = annotations[annotationsCursor];
    }

    // Next annotation is for a later line, don't advance past it.
    if (annotation.line != line) return null;
    annotationsCursor++;
    return annotation;
  }

  Element lineElement(ScriptLine line, int lineNumPad) {
    var e = new DivElement();
    e.classes.add("sourceRow");
    e.append(lineBreakpointElement(line));
    e.append(lineNumberElement(line, lineNumPad));
    if (_includeProfile) {
      e.append(lineProfileElement(line, false));
      e.append(lineProfileElement(line, true));
    }
    e.append(lineSourceElement(line));
    return e;
  }

  Element lineProfileElement(ScriptLine line, bool self) {
    var e = span('');
    e.classes.add('noCopy');
    if (self) {
      e.title = 'Self %';
    } else {
      e.title = 'Total %';
    }

    if (line == null) {
      e.classes.add('notSourceProfile');
      e.text = nbsp;
      return e;
    }

    var ranges = _rangeMap[line.line];
    if ((ranges == null) || ranges.isEmpty) {
      e.classes.add('notSourceProfile');
      e.text = nbsp;
      return e;
    }

    ScriptLineProfile lineProfile = _profileMap[line.line];
    if (lineProfile == null) {
      e.classes.add('noProfile');
      e.text = nbsp;
      return e;
    }

    if (self) {
      e.text = lineProfile.formattedSelfTicks;
    } else {
      e.text = lineProfile.formattedTotalTicks;
    }

    if (lineProfile.isHot(self)) {
      e.classes.add('hotProfile');
    } else if (lineProfile.isMedium(self)) {
      e.classes.add('mediumProfile');
    } else {
      e.classes.add('coldProfile');
    }

    return e;
  }

  Element lineBreakpointElement(ScriptLine line) {
    var e = new DivElement();
    if (line == null || !_possibleBreakpointLines.contains(line.line)) {
      e.classes.add('noCopy');
      e.classes.add("emptyBreakpoint");
      e.text = nbsp;
      return e;
    }

    e.text = 'B';
    var busy = false;
    void update() {
      e.classes.clear();
      e.classes.add('noCopy');
      if (busy) {
        e.classes.add("busyBreakpoint");
      } else if (line.breakpoints != null) {
        bool resolved = false;
        for (var bpt in line.breakpoints) {
          if (bpt.resolved) {
            resolved = true;
            break;
          }
        }
        if (resolved) {
          e.classes.add("resolvedBreakpoint");
        } else {
          e.classes.add("unresolvedBreakpoint");
        }
      } else {
        e.classes.add("possibleBreakpoint");
      }
    }

    line.changes.listen((_) => update());
    e.onClick.listen((event) {
      if (busy) {
        return;
      }
      busy = true;
      if (line.breakpoints == null) {
        // No breakpoint.  Add it.
        line.script.isolate.addBreakpoint(line.script, line.line)
          .catchError((e, st) {
            if (e is! ServerRpcException ||
                (e as ServerRpcException).code !=
                ServerRpcException.kCannotAddBreakpoint) {
              app.handleException(e, st);
            }})
          .whenComplete(() {
            busy = false;
            update();
          });
      } else {
        // Existing breakpoint.  Remove it.
        List pending = [];
        for (var bpt in line.breakpoints) {
          pending.add(line.script.isolate.removeBreakpoint(bpt));
        }
        Future.wait(pending).then((_) {
          busy = false;
          update();
        });
      }
      update();
    });
    update();
    return e;
  }

  Element lineNumberElement(ScriptLine line, int lineNumPad) {
    var lineNumber = line == null ? "..." : line.line;
    var e = span("$nbsp${lineNumber.toString().padLeft(lineNumPad,nbsp)}$nbsp");
    e.classes.add('noCopy');
    if (lineNumber == _currentLine) {
      hitsCurrent(e);
      return e;
    }
    var ranges = _rangeMap[lineNumber];
    if ((ranges == null) || ranges.isEmpty) {
      // This line is not code.
      hitsUnknown(e);
      return e;
    }
    bool compiled = true;
    bool hasCallInfo = false;
    bool executed = false;
    for (var range in ranges) {
      if (range['compiled']) {
        for (var callSite in range['callSites']) {
          var callLine = line.script.tokenToLine(callSite['tokenPos']);
          if (lineNumber == callLine) {
            // The call site is on the current line.
            hasCallInfo = true;
            for (var cacheEntry in callSite['cacheEntries']) {
              if (cacheEntry['count'] > 0) {
                // If any call site on the line has been executed, we
                // mark the line as executed.
                executed = true;
                break;
              }
            }
          }
        }
      } else {
        // If any range isn't compiled, show the line as not compiled.
        // This is necessary so that nested functions appear to be uncompiled.
        compiled = false;
      }
    }
    if (executed) {
      hitsExecuted(e);
    } else if (hasCallInfo) {
      hitsNotExecuted(e);
    } else if (compiled) {
      hitsCompiled(e);
    } else {
      hitsNotCompiled(e);
    }
    return e;
  }

  Element lineSourceElement(ScriptLine line) {
    var e = new DivElement();
    e.classes.add("sourceItem");

    if (line != null) {
      if (line.line == _currentLine) {
        e.classes.add("currentLine");
      }

      e.id = makeLineId(line.line);

      var position = 0;
      consumeUntil(var stop) {
        if (stop <= position) {
          return null;  // Empty gap between annotations/boundries.
        }
        if (stop > line.text.length) {
          // Approximated token length can run past the end of the line.
          stop = line.text.length;
        }

        var chunk = line.text.substring(position, stop);
        var chunkNode = span(chunk);
        e.append(chunkNode);
        position = stop;
        return chunkNode;
      }

      // TODO(rmacnak): Tolerate overlapping annotations.
      var annotation;
      while ((annotation = nextAnnotationOnLine(line.line)) != null) {
        consumeUntil(annotation.columnStart);
        annotation.applyStyleTo(consumeUntil(annotation.columnStop));
      }
      consumeUntil(line.text.length);
    }

    // So blank lines are included when copying script to the clipboard.
    e.append(span('\n'));

    return e;
  }

  ScriptInsetElement.created()
      : super.created() {
    _updateTask = new Task(update);
  }
}

@CustomTag('refresh-button')
class RefreshButtonElement extends PolymerElement {
  RefreshButtonElement.created() : super.created();

  @published var callback = null;
  bool busy = false;

  Future buttonClick(var event, var b, var c) async {
    if (busy) {
      return;
    }
    busy = true;
    if (callback != null) {
      await callback();
    }
    busy = false;
  }
}


@CustomTag('toggle-button')
class ToggleButtonElement extends PolymerElement {
  ToggleButtonElement.created() : super.created();

  @published var callback = null;
  @observable bool enabled = false;

  Future buttonClick(var event, var b, var c) async {
    enabled = !enabled;
    if (callback != null) {
      await callback(enabled);
    }
  }
}


@CustomTag('source-inset')
class SourceInsetElement extends PolymerElement {
  SourceInsetElement.created() : super.created();

  @published SourceLocation location;
  @published String height = null;
  @published int currentPos;
  @published bool inDebuggerContext = false;
  @published ObservableList variables;
  @published Element scroller;
}
