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

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 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 = 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 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 = 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 = 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) {
        annotations.add(
          new Annotation(
            collection.getIndex(location),
            codeOffset,
            location.shortText,
          ),
        );
      }
    });
    return convertAnnotatedCodeToHtml(
      text,
      annotations,
      colorScheme: colorScheme,
      elementScheme: 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(),
  required ElementScheme elementScheme,
  required int windowSize,
}) {
  StringBuffer htmlBuffer = StringBuffer();
  List<CodeLine> lines = convertAnnotatedCodeToCodeLines(
    code,
    annotations,
    windowSize: windowSize,
  );
  int? lineNoWidth;
  if (lines.isNotEmpty) {
    lineNoWidth = '${lines.last.lineNo + 1}'.length;
  }
  HtmlPrintContext context = 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;
  late final int firstLine;
  late final 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 = 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);
  }

  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 = 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 = 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 = SourceLocationCollection(collection);
  CodeProcessor codeProcessor = 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 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 = 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 = 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 = StringBuffer();
  Map<Uri, Map<int, List<SourceLocation>>> sourceLocationMap = {};
  collection.sourceLocations.forEach((SourceLocation sourceLocation) {
    if (sourceLocation.sourceUri == 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 = 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 = 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!);
      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();
}
