// Copyright (c) 2015, 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.

/// Helper for creating HTML visualization of the source map information
/// generated by a [SourceMapProcessor].

library sourcemap.html.helper;

import 'dart:convert';
import 'dart:math' as Math;

import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/io/source_information.dart';
import 'package:compiler/src/js/js.dart' as js;

import 'colors.dart';
import 'sourcemap_helper.dart';
import 'sourcemap_html_templates.dart';
import 'html_parts.dart';

/// Truncate [input] to [length], adding '...' if truncated.
String truncate(String input, int length) {
  if (input.length > length) {
    return '${input.substring(0, length - 3)}...';
  }
  return input;
}

/// Returns the [index]th color for visualization.
HSV toColor(int index) {
  int hueCount = 24;
  double h = 360.0 * (index % hueCount) / hueCount;
  double v = 1.0;
  double s = 0.5;
  return new HSV(h, s, v);
}

/// Return the CSS color value for the [index]th color.
String toColorCss(int index) {
  return toColor(index).toCss;
}

/// Return the CSS color value for the [index]th span.
String toPattern(int index) {
  /// Use gradient on spans to visually identify consecutive spans mapped to the
  /// same source location.
  HSV startColor = toColor(index);
  HSV endColor = new HSV(startColor.h, startColor.s + 0.4, startColor.v - 0.2);
  return 'linear-gradient(to right, ${startColor.toCss}, ${endColor.toCss})';
}

/// Return the html for the [index] line number. If [width] is provided, shorter
/// line numbers will be prefixed with spaces to match the width.
String lineNumber(int index, {int width, bool useNbsp: false}) {
  String text = '${index + 1}';
  String padding = useNbsp ? '&nbsp;' : ' ';
  if (width != null && text.length < width) {
    text = (padding * (width - text.length)) + text;
  }
  return '<span class="lineNumber">$text$padding</span>';
}

/// Return the html escaped [text].
String escape(String text) {
  return const HtmlEscape().convert(text);
}

/// Information needed to generate HTML for a single [SourceMapInfo].
class SourceMapHtmlInfo {
  final SourceMapInfo sourceMapInfo;
  final CodeProcessor codeProcessor;
  final SourceLocationCollection sourceLocationCollection;

  SourceMapHtmlInfo(this.sourceMapInfo,
                    this.codeProcessor,
                    this.sourceLocationCollection);

  String toString() {
    return sourceMapInfo.toString();
  }
}

/// A collection of source locations.
///
/// Used to index source locations for visualization and linking.
class SourceLocationCollection {
  List<SourceLocation> sourceLocations = [];
  Map<SourceLocation, int> sourceLocationIndexMap;

  SourceLocationCollection([SourceLocationCollection parent])
      : sourceLocationIndexMap =
            parent == null ? {} : parent.sourceLocationIndexMap;

  int registerSourceLocation(SourceLocation sourceLocation) {
    return sourceLocationIndexMap.putIfAbsent(sourceLocation, () {
      sourceLocations.add(sourceLocation);
      return sourceLocationIndexMap.length;
    });
  }

  int getIndex(SourceLocation sourceLocation) {
    return sourceLocationIndexMap[sourceLocation];
  }
}

abstract class CssColorScheme {
  String singleLocationToCssColor(var id);

  String multiLocationToCssColor(List ids);

  bool get showLocationAsSpan;
}

class CustomColorScheme implements CssColorScheme {
  final bool showLocationAsSpan;
  final Function single;
  final Function multi;

  CustomColorScheme(
      {this.showLocationAsSpan: false,
       String this.single(var id),
       String this.multi(List ids)});

  String singleLocationToCssColor(var id) => single != null ? single(id) : null;

  String multiLocationToCssColor(List ids) => multi != null ? multi(ids) : null;
}

class PatternCssColorScheme implements CssColorScheme {
  const PatternCssColorScheme();

  bool get showLocationAsSpan => true;

  String singleLocationToCssColor(int index) {
    return "background:${toPattern(index)};";
  }

  String multiLocationToCssColor(List<int> indices) {

    StringBuffer sb = new StringBuffer();
    double delta = 100.0 / (indices.length);
    double position = 0.0;

    void addColor(String color) {
      sb.write(', ${color} ${position.toInt()}%');
      position += delta;
      sb.write(', ${color} ${position.toInt()}%');
    }

    for (int index in indices) {
      addColor('${toColorCss(index)}');
    }
    return 'background: linear-gradient(to right${sb}); '
           'background-size: 10px 10px;';
  }
}

class SingleColorScheme implements CssColorScheme {
  const SingleColorScheme();

  bool get showLocationAsSpan => false;

  String singleLocationToCssColor(int index) {
    return "background:${toColorCss(index)};";
  }

  String multiLocationToCssColor(List<int> indices) {
    StringBuffer sb = new StringBuffer();
    double delta = 100.0 / (indices.length);
    double position = 0.0;

    void addColor(String color) {
      sb.write(', ${color} ${position.toInt()}%');
      position += delta;
      sb.write(', ${color} ${position.toInt()}%');
    }

    for (int index in indices) {
      addColor('${toColorCss(index)}');
    }
    return 'background: linear-gradient(to bottom${sb}); '
           'background-size: 10px 3px;';
  }
}

/// Processor that computes the HTML representation of a block of JavaScript
/// code and collects the source locations mapped in the code.
class CodeProcessor {
  int lineIndex = 0;
  final String name;
  int currentJsSourceOffset = 0;
  final SourceLocationCollection collection;
  final Map<int, List<SourceLocation>> codeLocations = {};
  final CssColorScheme colorScheme;

  CodeProcessor(this.name, this.collection,
      {this.colorScheme: const PatternCssColorScheme()});

  void addSourceLocation(int targetOffset, SourceLocation sourceLocation) {
    codeLocations.putIfAbsent(targetOffset, () => []).add(sourceLocation);
    collection.registerSourceLocation(sourceLocation);
  }

  String convertToHtml(String text) {
    List<Annotation> annotations = <Annotation>[];
    codeLocations.forEach((int codeOffset, List<SourceLocation> locations) {
      for (SourceLocation location in locations) {
        if (location != null) {
          annotations.add(new Annotation(
              collection.getIndex(location),
              codeOffset,
              location.shortText));
        }
      }
    });
    return convertAnnotatedCodeToHtml(
        text, annotations, colorScheme: colorScheme,
        elementScheme: new HighlightLinkScheme(name),
        windowSize: 3);
  }
}

class Annotation {
  final id;
  final int codeOffset;
  final String title;

  Annotation(this.id, this.codeOffset, this.title);
}

class ElementScheme {
  const ElementScheme();

  String getName(var id, Set ids) => null;
  String getHref(var id, Set ids) => null;
  String onClick(var id, Set ids) => null;
  String onMouseOver(var id, Set ids) => null;
  String onMouseOut(var id, Set ids) => null;
}

class HighlightLinkScheme implements ElementScheme {
  final String name;

  HighlightLinkScheme(this.name);

  @override
  String getName(int id, Set<int> indices) {
    return 'js$id';
  }

  @override
  String getHref(int id, Set<int> indices) {
    return "#${id}";
  }

  @override
  String onClick(int id, Set<int> indices) {
    return "show(\'$name\');";
  }

  @override
  String onMouseOut(int id, Set<int> indices) {
    String onmouseover = indices.map((i) => '\'$i\'').join(',');
    return "highlight([${onmouseover}]);";
  }

  @override
  String onMouseOver(int id, Set<int> indices) {
    return "highlight([]);";
  }
}

String convertAnnotatedCodeToHtml(
    String code,
    Iterable<Annotation> annotations,
    {CssColorScheme colorScheme: const SingleColorScheme(),
     ElementScheme elementScheme: const ElementScheme(),
     int windowSize}) {
  StringBuffer htmlBuffer = new StringBuffer();
  List<CodeLine> lines = convertAnnotatedCodeToCodeLines(
      code, annotations,
      colorScheme: colorScheme,
      elementScheme: elementScheme,
      windowSize: windowSize);
  int lineNoWidth;
  if (lines.isNotEmpty) {
    lineNoWidth = '${lines.last.lineNo + 1}'.length;
  }
  HtmlPrintContext context = new HtmlPrintContext(lineNoWidth: lineNoWidth);
  for (CodeLine line in lines) {
    line.printHtmlOn(htmlBuffer, context);
  }
  return htmlBuffer.toString();
}

List<CodeLine> convertAnnotatedCodeToCodeLines(
    String code,
    Iterable<Annotation> annotations,
    {CssColorScheme colorScheme: const SingleColorScheme(),
     ElementScheme elementScheme: const ElementScheme(),
     int windowSize}) {

  List<CodeLine> lines = <CodeLine>[];
  CodeLine currentLine;
  int offset = 0;
  int lineIndex = 0;
  int firstLine;
  int lastLine;
  bool pendingSourceLocationsEnd = false;

  void write(String code, HtmlPart html) {
    if (currentLine != null) {
      currentLine.codeBuffer.write(code);
      currentLine.htmlParts.add(html);
    }
  }

  void startLine(int currentOffset) {
    lines.add(currentLine = new CodeLine(lines.length, currentOffset));
  }

  void endCurrentLocation() {
    if (pendingSourceLocationsEnd) {
      write('', const ConstHtmlPart('</a>'));
    }
    pendingSourceLocationsEnd = false;
  }

  void addSubstring(int until, {bool isFirst: false, bool isLast: false}) {
    if (until <= offset) return;
    if (offset >= code.length) return;

    String substring = code.substring(offset, until);
    bool first = true;

    if (isLast) {
      lastLine = lineIndex;
    }
    int localOffset = 0;
    if (isFirst) {
      startLine(offset + localOffset);
    }
    for (String line in substring.split('\n')) {
      if (!first) {
        endCurrentLocation();
        write('', const NewLine());
        lineIndex++;
        startLine(offset + localOffset);
      }
      if (pendingSourceLocationsEnd && !colorScheme.showLocationAsSpan) {
        if (line.isNotEmpty) {
          String before = line.substring(0, 1);
          write(before, new HtmlText(before));
          endCurrentLocation();
          String after = line.substring(1);
          write(after, new HtmlText(after));
        }
      } else {
        write(line, new HtmlText(line));
      }
      first = false;
      localOffset += line.length + 1;
    }
    if (isFirst) {
      firstLine = lineIndex;
    }
    offset = until;
  }

  void insertAnnotations(List<Annotation> annotations) {
    endCurrentLocation();

    String color;
    var id;
    String title;
    if (annotations.length == 1) {
      Annotation annotation = annotations.single;
      if (annotation != null) {
        id = annotation.id;
        color = colorScheme.singleLocationToCssColor(id);
        title = annotation.title;
      }
    } else {
      id = annotations.first.id;
      List ids = [];
      for (Annotation annotation in annotations) {
        ids.add(annotation.id);
      }
      color = colorScheme.multiLocationToCssColor(ids);
      title = annotations.map((l) => l.title).join(',');
    }
    if (id != null) {
      Set ids = annotations.map((l) => l.id).toSet();
      String name = elementScheme.getName(id, ids);
      String href = elementScheme.getHref(id, ids);
      String onclick = elementScheme.onClick(id, ids);
      String onmouseover = elementScheme.onMouseOver(id, ids);
      String onmouseout = elementScheme.onMouseOut(id, ids);
      write('', new AnchorHtmlPart(
          color: color,
          name: name,
          href: href,
          title: title,
          onclick: onclick,
          onmouseover: onmouseover,
          onmouseout: onmouseout));
      pendingSourceLocationsEnd = true;
    }
    currentLine.annotations.addAll(annotations);
    if (annotations.last == null) {
      endCurrentLocation();
    }
  }

  Map<int, List<Annotation>> annotationMap = <int, List<Annotation>>{};
  for (Annotation annotation in annotations) {
    annotationMap.putIfAbsent(annotation.codeOffset, () => <Annotation>[])
                 .add(annotation);
  }

  bool first = true;
  for (int codeOffset in annotationMap.keys.toList()..sort()) {
    List<Annotation> annotationList = annotationMap[codeOffset];
    addSubstring(codeOffset, isFirst: first);
    insertAnnotations(annotationList);
    first = false;
  }

  addSubstring(code.length, isFirst: first, isLast: true);
  endCurrentLocation();

  int start = 0;
  int end = lines.length - 1;
  if (windowSize != null) {
    start = Math.max(firstLine - windowSize, start);
    end = Math.min(lastLine + windowSize, end);
  }
  return lines.sublist(start, end);
}

/// Computes the HTML representation for a collection of JavaScript code blocks.
String computeJsHtml(Iterable<SourceMapHtmlInfo> infoList) {

  StringBuffer jsCodeBuffer = new StringBuffer();
  for (SourceMapHtmlInfo info in infoList) {
    String name = info.sourceMapInfo.name;
    String html = info.codeProcessor.convertToHtml(info.sourceMapInfo.code);
    String onclick = 'show(\'$name\');';
    jsCodeBuffer.write(
        '<h3 onclick="$onclick">JS code for: ${escape(name)}</h3>\n');
    jsCodeBuffer.write('''
<pre>
$html
</pre>
''');
  }
  return jsCodeBuffer.toString();
}

/// Computes the HTML representation of the source mapping information for a
/// collection of JavaScript code blocks.
String computeJsTraceHtml(Iterable<SourceMapHtmlInfo> infoList) {
  StringBuffer jsTraceBuffer = new StringBuffer();
  for (SourceMapHtmlInfo info in infoList) {
    String name = info.sourceMapInfo.name;
    String jsTrace = computeJsTraceHtmlPart(
        info.sourceMapInfo.codePoints, info.sourceLocationCollection);
    jsTraceBuffer.write('''
<div name="$name" class="js-trace-buffer" style="display:none;">
<h3>Trace for: ${escape(name)}</h3>
$jsTrace
</div>
''');
  }
  return jsTraceBuffer.toString();
}

/// Computes the HTML information for the [info].
SourceMapHtmlInfo createHtmlInfo(SourceLocationCollection collection,
                                 SourceMapInfo info) {
  js.Node node = info.node;
  String code = info.code;
  String name = info.name;
  SourceLocationCollection subcollection =
      new SourceLocationCollection(collection);
  CodeProcessor codeProcessor = new CodeProcessor(name, subcollection);
  for (js.Node node in info.nodeMap.nodes) {
    info.nodeMap[node].forEach(
        (int targetOffset, List<SourceLocation> sourceLocations) {
      for (SourceLocation sourceLocation in sourceLocations) {
        codeProcessor.addSourceLocation(targetOffset, sourceLocation);
      }
    });
  }
  return new SourceMapHtmlInfo(info, codeProcessor, subcollection);
}

/// Outputs a HTML file in [jsMapHtmlUri] containing an interactive
/// visualization of the source mapping information in [infoList] computed
/// with the [sourceMapProcessor].
void createTraceSourceMapHtml(Uri jsMapHtmlUri,
                              SourceMapProcessor sourceMapProcessor,
                              Iterable<SourceMapInfo> infoList) {
  SourceFileManager sourceFileManager = sourceMapProcessor.sourceFileManager;
  SourceLocationCollection collection = new SourceLocationCollection();
  List<SourceMapHtmlInfo> htmlInfoList = <SourceMapHtmlInfo>[];
  for (SourceMapInfo info in infoList) {
    htmlInfoList.add(createHtmlInfo(collection, info));
  }

  String jsCode = computeJsHtml(htmlInfoList);
  String dartCode = computeDartHtml(sourceFileManager, htmlInfoList);

  String jsTraceHtml = computeJsTraceHtml(htmlInfoList);
  outputJsDartTrace(jsMapHtmlUri, jsCode, dartCode, jsTraceHtml);
  print('Trace source map html generated: $jsMapHtmlUri');
}

/// Computes the HTML representation for the Dart code snippets referenced in
/// [infoList].
String computeDartHtml(
    SourceFileManager sourceFileManager,
    Iterable<SourceMapHtmlInfo> infoList) {

  StringBuffer dartCodeBuffer = new StringBuffer();
  for (SourceMapHtmlInfo info in infoList) {
    dartCodeBuffer.write(computeDartHtmlPart(info.sourceMapInfo.name,
         sourceFileManager, info.sourceLocationCollection));
  }
  return dartCodeBuffer.toString();

}

/// Computes the HTML representation for the Dart code snippets in [collection].
String computeDartHtmlPart(String name,
                           SourceFileManager sourceFileManager,
                           SourceLocationCollection collection,
                           {bool showAsBlock: false}) {
  const int windowSize = 3;
  StringBuffer dartCodeBuffer = new StringBuffer();
  Map<Uri, Map<int, List<SourceLocation>>> sourceLocationMap = {};
  collection.sourceLocations.forEach((SourceLocation sourceLocation) {
    Map<int, List<SourceLocation>> uriMap =
        sourceLocationMap.putIfAbsent(sourceLocation.sourceUri, () => {});
    List<SourceLocation> lineList =
        uriMap.putIfAbsent(sourceLocation.line, () => []);
    lineList.add(sourceLocation);
  });
  sourceLocationMap.forEach((Uri uri, Map<int, List<SourceLocation>> uriMap) {
    SourceFile sourceFile = sourceFileManager.getSourceFile(uri);
    if (sourceFile == null) return;
    StringBuffer codeBuffer = new StringBuffer();

    int firstLineIndex;
    int lastLineIndex;
    List<int> lineIndices = uriMap.keys.toList()..sort();
    int lineNoWidth;
    if (lineIndices.isNotEmpty) {
      lineNoWidth = '${lineIndices.last + windowSize + 1}'.length;
    }

    void flush() {
      if (firstLineIndex != null && lastLineIndex != null) {
        dartCodeBuffer.write(
            '<h4>${uri.pathSegments.last}, '
            '${firstLineIndex - windowSize + 1}-'
            '${lastLineIndex + windowSize + 1}'
            '</h4>\n');
        dartCodeBuffer.write('<pre>\n');
        for (int line = firstLineIndex - windowSize;
             line < firstLineIndex;
             line++) {
          if (line >= 0) {
            dartCodeBuffer.write(lineNumber(line, width: lineNoWidth));
            dartCodeBuffer.write(sourceFile.getLineText(line));
          }
        }
        dartCodeBuffer.write(codeBuffer);
        for (int line = lastLineIndex + 1;
             line <= lastLineIndex + windowSize;
             line++) {
          if (line < sourceFile.lines) {
            dartCodeBuffer.write(lineNumber(line, width: lineNoWidth));
            dartCodeBuffer.write(sourceFile.getLineText(line));
          }
        }
        dartCodeBuffer.write('</pre>\n');
        firstLineIndex = null;
        lastLineIndex = null;
      }
      codeBuffer.clear();
    }

    lineIndices.forEach((int lineIndex) {
      List<SourceLocation> locations = uriMap[lineIndex];
      if (lastLineIndex != null &&
          lastLineIndex + windowSize * 4 < lineIndex) {
        flush();
      }
      if (firstLineIndex == null) {
        firstLineIndex = lineIndex;
      } else {
        for (int line = lastLineIndex + 1; line < lineIndex; line++) {
          codeBuffer.write(lineNumber(line, width: lineNoWidth));
          codeBuffer.write(sourceFile.getLineText(line));
        }
      }
      String line = sourceFile.getLineText(lineIndex);
      locations.sort((a, b) => a.offset.compareTo(b.offset));
      for (int i = 0; i < locations.length; i++) {
        SourceLocation sourceLocation = locations[i];
        int index = collection.getIndex(sourceLocation);
        int start = sourceLocation.column;
        int end = line.length;
        if (i + 1 < locations.length) {
          end = locations[i + 1].column;
        }
        if (i == 0) {
          codeBuffer.write(lineNumber(lineIndex, width: lineNoWidth));
          codeBuffer.write(line.substring(0, start));
        }
        codeBuffer.write(
            '<a name="${index}" style="background:${toPattern(index)};" '
            'title="[${lineIndex + 1},${start + 1}]" '
            'onmouseover="highlight(\'$index\');" '
            'onmouseout="highlight();">');
        codeBuffer.write(line.substring(start, end));
        codeBuffer.write('</a>');
      }
      lastLineIndex = lineIndex;
    });

    flush();
  });
  String display = showAsBlock ? 'block' : 'none';
  return '''
<div name="$name" class="dart-buffer" style="display:$display;">
<h3>Dart code for: ${escape(name)}</h3>
${dartCodeBuffer}
</div>''';
}

/// Computes a HTML visualization of the [codePoints].
String computeJsTraceHtmlPart(List<CodePoint> codePoints,
                              SourceLocationCollection collection) {
  StringBuffer buffer = new StringBuffer();
  buffer.write('<table style="width:100%;">');
  buffer.write(
      '<tr><th>Node kind</th><th>JS code @ offset</th>'
      '<th>Dart code @ mapped location</th><th>file:position:name</th></tr>');
  codePoints.forEach((CodePoint codePoint) {
    String jsCode = truncate(codePoint.jsCode, 50);
    if (codePoint.sourceLocation != null) {
      int index = collection.getIndex(codePoint.sourceLocation);
      if (index != null) {
        String style = '';
        if (!codePoint.isMissing) {
          style = 'style="background:${toColorCss(index)};" ';
        }
        buffer.write('<tr $style'
                     'name="trace$index" '
                     'onmouseover="highlight([${index}]);"'
                     'onmouseout="highlight([]);">');
      } else {
        buffer.write('<tr>');
        print('${codePoint.sourceLocation} not found in ');
        collection.sourceLocationIndexMap.keys
            .where((l) => l.sourceUri == codePoint.sourceLocation.sourceUri)
            .forEach((l) => print(' $l'));
      }
    } else {
      buffer.write('<tr>');
    }
    buffer.write('<td>${codePoint.kind}</td>');
    buffer.write('<td class="code">${jsCode}</td>');
    if (codePoint.sourceLocation == null) {
      //buffer.write('<td></td>');
    } else {
      String dartCode = truncate(codePoint.dartCode, 50);
      buffer.write('<td class="code">${dartCode}</td>');
      buffer.write('<td>${escape(codePoint.sourceLocation.shortText)}</td>');
    }
    buffer.write('</tr>');
  });
  buffer.write('</table>');

  return buffer.toString();
}
