// 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.

// @dart = 2.7

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

const int HUE_COUNT = 24;

/// Returns the [index]th color for visualization.
HSV toColor(int index) {
  double h = 360.0 * (index % HUE_COUNT) / HUE_COUNT;
  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 className}) {
  if (className == null) {
    className = 'lineNumber';
  }
  String text = '${index + 1}';
  String padding = useNbsp ? '&nbsp;' : ' ';
  if (width != null && text.length < width) {
    text = (padding * (width - text.length)) + text;
  }
  return '<span class="$className">$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);

  @override
  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(int id);

  String multiLocationToCssColor(List<int> ids);

  bool get showLocationAsSpan;
}

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

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

  @override
  String singleLocationToCssColor(int id) => single != null ? single(id) : null;

  @override
  String multiLocationToCssColor(List<int> ids) =>
      multi != null ? multi(ids) : null;
}

class PatternCssColorScheme implements CssColorScheme {
  const PatternCssColorScheme();

  @override
  bool get showLocationAsSpan => true;

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

  @override
  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();

  @override
  bool get showLocationAsSpan => false;

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

  @override
  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 ElementScheme {
  const ElementScheme();

  String getName(int id, Set<int> ids) => null;
  String getHref(int id, Set<int> ids) => null;
  String onClick(int id, Set<int> ids) => null;
  String onMouseOver(int id, Set<int> ids) => null;
  String onMouseOut(int id, Set<int> 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) {
    return "highlight([]);";
  }

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

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,
      windowSize: windowSize);
  int lineNoWidth;
  if (lines.isNotEmpty) {
    lineNoWidth = '${lines.last.lineNo + 1}'.length;
  }
  HtmlPrintContext context = new HtmlPrintContext(
      lineNoWidth: lineNoWidth,
      getAnnotationData: createAnnotationDataFunction(
          colorScheme: colorScheme, elementScheme: elementScheme));
  for (CodeLine line in lines) {
    line.printHtmlOn(htmlBuffer, context);
  }
  return htmlBuffer.toString();
}

List<CodeLine> convertAnnotatedCodeToCodeLines(
    String code, Iterable<Annotation> annotations,
    {int startLine, int endLine, int windowSize, Uri uri}) {
  List<CodeLine> lines = <CodeLine>[];
  CodeLine currentLine;
  final List<Annotation> currentAnnotations = <Annotation>[];
  int offset = 0;
  int lineIndex = 0;
  int firstLine;
  int lastLine;

  void addCode(String code) {
    if (currentLine != null) {
      currentLine.codeBuffer.write(code);
      currentLine.codeParts
          .add(new CodePart(currentAnnotations.toList(), code));
      currentAnnotations.clear();
    }
  }

  void addAnnotations(List<Annotation> annotations) {
    currentAnnotations.addAll(annotations);
    if (currentLine != null) {
      currentLine.annotations.addAll(annotations);
    }
  }

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

  void endCurrentLocation() {
    if (currentAnnotations.isNotEmpty) {
      addCode('');
    }
  }

  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) {
      beginLine(offset + localOffset);
    }
    for (String line in substring.split('\n')) {
      if (!first) {
        endCurrentLocation();
        lineIndex++;
        beginLine(offset + localOffset);
      }
      addCode(line);
      first = false;
      localOffset += line.length + 1;
    }
    if (isFirst) {
      firstLine = lineIndex;
    }
    offset = until;
  }

  void insertAnnotations(List<Annotation> annotations) {
    endCurrentLocation();
    addAnnotations(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 = startLine ?? 0;
  int end = endLine ?? lines.length - 1;
  if (lastLine == 0) lastLine = firstLine;
  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) {
  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) {
    if (sourceLocation.sourceUri == null || sourceLocation.line == null) return;
    Map<int, List<SourceLocation>> uriMap =
        sourceLocationMap.putIfAbsent(sourceLocation.sourceUri, () => {});
    List<SourceLocation> lineList =
        uriMap.putIfAbsent(sourceLocation.line - 1, () => []);
    lineList.add(sourceLocation);
  });
  sourceLocationMap.forEach((Uri uri, Map<int, List<SourceLocation>> uriMap) {
    SourceFile sourceFile = sourceFileManager.getSourceFile(uri);
    if (sourceFile == null) {
      print('No source file for $uri');
      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');
        dartCodeBuffer.write('<p class="line">');
        for (int line = firstLineIndex - windowSize;
            line < firstLineIndex;
            line++) {
          if (line >= 0) {
            dartCodeBuffer.write('</p><p class="line">');
            dartCodeBuffer.write(lineNumber(line, width: lineNoWidth));
            dartCodeBuffer.write(sourceFile.kernelSource.getTextLine(line + 1));
          }
        }
        dartCodeBuffer.write(codeBuffer);
        for (int line = lastLineIndex + 1;
            line <= lastLineIndex + windowSize;
            line++) {
          if (line < sourceFile.lines) {
            dartCodeBuffer.write('</p><p class="line">');
            dartCodeBuffer.write(lineNumber(line, width: lineNoWidth));
            dartCodeBuffer.write(sourceFile.kernelSource.getTextLine(line + 1));
          }
        }
        dartCodeBuffer.write('</p>');
        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('</p><p class="line">');
          codeBuffer.write(lineNumber(line, width: lineNoWidth));
          codeBuffer.write(sourceFile.kernelSource.getTextLine(line + 1));
        }
      }
      String line = sourceFile.kernelSource.getTextLine(lineIndex + 1);
      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 - 1;
        int end = line.length;
        if (i + 1 < locations.length) {
          end = locations[i + 1].column - 1;
        }
        if (i == 0) {
          codeBuffer.write('</p><p class="line">');
          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">${codePoint.targetOffset}:${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();
}
