// Copyright (c) 2016, 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 sourcemap.diff;

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

import 'html_parts.dart';
import 'output_structure.dart';
import 'sourcemap_helper.dart';
import 'sourcemap_html_helper.dart';

enum DiffKind { UNMATCHED, MATCHING, IDENTICAL }

/// Id for an output column.
class DiffColumn {
  final String type;
  final int? index;

  const DiffColumn(this.type, [this.index]);

  @override
  int get hashCode => type.hashCode * 19 + index.hashCode * 23;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! DiffColumn) return false;
    return type == other.type && index == other.index;
  }

  @override
  String toString() => '$type${index ?? ''}';
}

/// A block of code in an output column.
abstract class DiffColumnBlock {
  void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context);
}

/// A block consisting of pure HTML parts.
class PartsColumnBlock extends DiffColumnBlock {
  final List<HtmlPart> parts;

  PartsColumnBlock(this.parts);

  @override
  void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
    if (parts.isNotEmpty) {
      for (HtmlPart part in parts) {
        part.printHtmlOn(htmlBuffer, context);
      }
    }
  }
}

/// A block consisting of line-per-line JavaScript and source mapped Dart code.
class CodeLinesColumnBlock extends DiffColumnBlock {
  final List<CodeLine> jsCodeLines;
  final Map<CodeLine, List<CodeLine>> jsToDartMap;

  CodeLinesColumnBlock(this.jsCodeLines, this.jsToDartMap);

  @override
  void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
    if (jsCodeLines.isNotEmpty) {
      htmlBuffer.write('<table style="width:100%">');
      for (CodeLine codeLine in jsCodeLines) {
        htmlBuffer.write('<tr><td class="${ClassNames.innerCell}">');
        codeLine.printHtmlOn(htmlBuffer, context);
        htmlBuffer.write(
          '</td><td '
          'class="${ClassNames.innerCell} ${ClassNames.sourceMapped}">',
        );
        List<CodeLine>? lines = jsToDartMap[codeLine];
        if (lines != null) {
          for (CodeLine line in lines) {
            line.printHtmlOn(
              htmlBuffer,
              context.from(
                includeAnnotation: (a) {
                  CodeLineAnnotation annotation = a.data;
                  return annotation.annotationType.isSourceMapped;
                },
              ),
            );
          }
        }
        htmlBuffer.write('</td></tr>');
      }
      htmlBuffer.write('</table>');
    }
  }
}

/// A list of columns that should align in output.
class DiffBlock {
  final DiffKind kind;
  final Map<DiffColumn, DiffColumnBlock> _columns =
      <DiffColumn, DiffColumnBlock>{};

  DiffBlock(this.kind);

  void addColumnBlock(DiffColumn column, DiffColumnBlock block) {
    _columns[column] = block;
  }

  Iterable<DiffColumn> get columns => _columns.keys;

  void printHtmlOn(
    DiffColumn column,
    StringBuffer htmlBuffer,
    HtmlPrintContext context,
  ) {
    DiffColumnBlock? block = _columns[column];
    if (block != null) {
      block.printHtmlOn(htmlBuffer, context);
    }
  }
}

bool _eq(a, b) => a == b;

/// Align the content of [list1] and [list2].
///
/// If provided, [range1] and [range2] aligned the subranges of [list1] and
/// [list2], otherwise the whole lists are aligned.
///
/// If provided, [match] determines the equality between members of [list1] and
/// [list2], otherwise `==` is used.
///
/// [handleSkew] is called when a subrange of one list is not found in the
/// other.
///
/// [handleMatched] is called when two indices match up.
///
/// [handleUnmatched] is called when two indices don't match up (none are found
/// in the other list).
void align(
  List list1,
  List list2, {
  Interval? range1,
  Interval? range2,
  bool match(a, b) = _eq,
  required void handleSkew(int listIndex, Interval range),
  required void handleMatched(List<int> indices),
  required void handleUnmatched(List<int> indices),
}) {
  range1 ??= Interval(0, list1.length);
  range2 ??= Interval(0, list2.length);

  Interval? findInOther(
    List thisLines,
    Interval thisRange,
    List otherLines,
    Interval otherRange,
  ) {
    for (int index = otherRange.from; index < otherRange.to; index++) {
      if (match(thisLines[thisRange.from], otherLines[index])) {
        int offset = 1;
        while (thisRange.from + offset < thisRange.to &&
            otherRange.from + offset < otherRange.to &&
            match(
              thisLines[thisRange.from + offset],
              otherLines[otherRange.from + offset],
            )) {
          offset++;
        }
        return Interval(index, index + offset);
      }
    }
    return null;
  }

  int start1 = range1.from;
  int end1 = range1.to;
  int start2 = range2.from;
  int end2 = range2.to;

  const int ALIGN1 = -1;
  const int UNMATCHED = 0;
  const int ALIGN2 = 1;

  while (start1 < end1 && start2 < end2) {
    if (match(list1[start1], list2[start2])) {
      handleMatched([start1++, start2++]);
    } else {
      Interval subrange1 = Interval(start1, end1);
      Interval subrange2 = Interval(start2, end2);
      Interval? element2inList1 = findInOther(
        list1,
        subrange1,
        list2,
        subrange2,
      );
      Interval? element1inList2 = findInOther(
        list2,
        subrange2,
        list1,
        subrange1,
      );
      int choice = 0;
      if (element2inList1 != null) {
        if (element1inList2 != null) {
          if (element1inList2.length > 1 && element2inList1.length > 1) {
            choice = element2inList1.from < element1inList2.from
                ? ALIGN2
                : ALIGN1;
          } else if (element2inList1.length > 1) {
            choice = ALIGN2;
          } else if (element1inList2.length > 1) {
            choice = ALIGN1;
          } else {
            choice = element2inList1.from < element1inList2.from
                ? ALIGN2
                : ALIGN1;
          }
        } else {
          choice = ALIGN2;
        }
      } else if (element1inList2 != null) {
        choice = ALIGN1;
      }
      switch (choice) {
        case ALIGN1:
          handleSkew(0, Interval(start1, element1inList2!.from));
          start1 = element1inList2.from;
          break;
        case ALIGN2:
          handleSkew(1, Interval(start2, element2inList1!.from));
          start2 = element2inList1.from;
          break;
        case UNMATCHED:
          handleUnmatched([start1++, start2++]);
          break;
      }
    }
  }
  if (start1 < end1) {
    handleSkew(0, Interval(start1, end1));
  }
  if (start2 < end2) {
    handleSkew(1, Interval(start2, end2));
  }
}

/// Create a list of blocks containing the diff of the two output [structures]
/// and the corresponding Dart code.
List<DiffBlock> createDiffBlocks(
  List<OutputStructure> structures,
  SourceFileManager sourceFileManager,
) {
  return DiffCreator(structures, sourceFileManager).computeBlocks();
}

class DiffCreator {
  final List<OutputStructure> structures;
  final SourceFileManager sourceFileManager;

  List<List<CodeLine>> inputLines;

  List<int> nextInputLine = [0, 0];

  List<DiffBlock> blocks = <DiffBlock>[];

  DiffCreator(List<OutputStructure> structures, this.sourceFileManager)
    : this.structures = structures,
      this.inputLines = structures.map((s) => s.lines).toList();

  /// Compute [CodeSource]s defined by [entities].
  Iterable<CodeSource> codeSourceFromEntities(Iterable<OutputEntity> entities) {
    Set<CodeSource> sources = Set<CodeSource>();
    for (OutputEntity entity in entities) {
      if (entity.codeSource != null) {
        sources.add(entity.codeSource!);
      }
    }
    return sources;
  }

  /// Create a block with the code from [codeSources]. The [CodeSource]s in
  /// [mainSources] are tagged as original code sources, the rest as inlined
  /// code sources.
  DiffColumnBlock codeLinesFromCodeSources(
    Iterable<CodeSource> mainSources,
    Iterable<CodeSource> codeSources,
  ) {
    List<HtmlPart> parts = <HtmlPart>[];
    for (CodeSource codeSource in codeSources) {
      //parts.addAll(codeLinesFromCodeSource(codeSource));
      String className = mainSources.contains(codeSource)
          ? ClassNames.originalDart
          : ClassNames.inlinedDart;
      parts.add(
        new TagPart(
          'div',
          properties: {'class': className},
          content: codeLinesFromCodeSource(codeSource),
        ),
      );
    }
    return PartsColumnBlock(parts);
  }

  /// Adds all [CodeSource]s used in [dartCodeLines] to [codeSourceSet].
  void collectCodeSources(
    Set<CodeSource> codeSourceSet,
    Map<CodeLine, List<CodeLine>> dartCodeLines,
  ) {
    for (List<CodeLine> codeLines in dartCodeLines.values) {
      for (CodeLine dartCodeLine in codeLines) {
        if (dartCodeLine.lineAnnotation != null) {
          codeSourceSet.add(dartCodeLine.lineAnnotation);
        }
      }
    }
  }

  /// Checks that lines are added in sequence without gaps or duplicates.
  void checkLineInvariant(int index, Interval range) {
    int expectedLineNo = nextInputLine[index];
    if (range.from != expectedLineNo) {
      print('Expected line no $expectedLineNo, found ${range.from}');
      if (range.from < expectedLineNo) {
        print('Duplicate lines:');
        int i = range.from;
        while (i <= expectedLineNo) {
          print(inputLines[index][i++].code);
        }
      } else {
        print('Missing lines:');
        int i = expectedLineNo;
        while (i <= range.from) {
          print(inputLines[index][i++].code);
        }
      }
    }
    nextInputLine[index] = range.to;
  }

  /// Creates a block containing the code lines in [range] from input number
  /// [index]. If [codeSource] is provided, the block will contain a
  /// corresponding Dart code column.
  void handleSkew(
    int index,
    Interval range, [
    Iterable<CodeSource> mainCodeSources = const <CodeSource>[],
  ]) {
    if (range.isEmpty) return;

    Set<CodeSource> codeSources = Set<CodeSource>();
    codeSources.addAll(mainCodeSources);

    DiffBlock block = DiffBlock(DiffKind.UNMATCHED);
    checkLineInvariant(index, range);
    List<CodeLine> jsCodeLines = inputLines[index].sublist(
      range.from,
      range.to,
    );
    Map<CodeLine, List<CodeLine>> dartCodeLines = dartCodeLinesFromJsCodeLines(
      jsCodeLines,
    );
    block.addColumnBlock(
      new DiffColumn('js', index),
      CodeLinesColumnBlock(jsCodeLines, dartCodeLines),
    );
    collectCodeSources(codeSources, dartCodeLines);

    if (codeSources.isNotEmpty) {
      block.addColumnBlock(
        const DiffColumn('dart'),
        codeLinesFromCodeSources(mainCodeSources, codeSources),
      );
    }
    blocks.add(block);
  }

  /// Create a block containing the code lines in [ranges] from the
  /// corresponding JavaScript inputs. If [codeSource] is provided, the block
  /// will contain a corresponding Dart code column.
  void addLines(
    DiffKind kind,
    List<Interval> ranges, [
    Iterable<CodeSource> mainCodeSources = const <CodeSource>[],
  ]) {
    if (ranges.every((range) => range.isEmpty)) return;

    Set<CodeSource> codeSources = Set<CodeSource>();
    codeSources.addAll(mainCodeSources);

    DiffBlock block = DiffBlock(kind);
    for (int i = 0; i < ranges.length; i++) {
      checkLineInvariant(i, ranges[i]);
      List<CodeLine> jsCodeLines = inputLines[i].sublist(
        ranges[i].from,
        ranges[i].to,
      );
      Map<CodeLine, List<CodeLine>> dartCodeLines =
          dartCodeLinesFromJsCodeLines(jsCodeLines);
      block.addColumnBlock(
        new DiffColumn('js', i),
        CodeLinesColumnBlock(jsCodeLines, dartCodeLines),
      );
      collectCodeSources(codeSources, dartCodeLines);
    }
    if (codeSources.isNotEmpty) {
      block.addColumnBlock(
        const DiffColumn('dart'),
        codeLinesFromCodeSources(mainCodeSources, codeSources),
      );
    }
    blocks.add(block);
  }

  /// Merge the code lines in [range1] and [range2] of the corresponding input.
  void addRaw(Interval range1, Interval range2) {
    if (range1.isEmpty && range2.isEmpty) return;

    match(a, b) => a.code == b.code;

    List<Interval>? currentMatchedIntervals;
    List<Interval>? currentUnmatchedIntervals;

    void flushMatching() {
      if (currentMatchedIntervals != null) {
        addLines(DiffKind.IDENTICAL, currentMatchedIntervals!);
      }
      currentMatchedIntervals = null;
    }

    void flushUnmatched() {
      if (currentUnmatchedIntervals != null) {
        addLines(DiffKind.UNMATCHED, currentUnmatchedIntervals!);
      }
      currentUnmatchedIntervals = null;
    }

    List<Interval> updateIntervals(List<Interval>? current, List<int> indices) {
      if (current == null) {
        return [
          Interval(indices[0], indices[0] + 1),
          Interval(indices[1], indices[1] + 1),
        ];
      } else {
        current[0] = Interval(current[0].from, indices[0] + 1);
        current[1] = Interval(current[1].from, indices[1] + 1);
        return current;
      }
    }

    align(
      inputLines[0],
      inputLines[1],
      range1: range1,
      range2: range2,
      match: match,
      handleSkew: (int listIndex, Interval range) {
        flushMatching();
        flushUnmatched();
        handleSkew(listIndex, range);
      },
      handleMatched: (List<int> indices) {
        flushUnmatched();
        currentMatchedIntervals = updateIntervals(
          currentMatchedIntervals,
          indices,
        );
      },
      handleUnmatched: (List<int> indices) {
        flushMatching();
        currentUnmatchedIntervals = updateIntervals(
          currentUnmatchedIntervals,
          indices,
        );
      },
    );

    flushMatching();
    flushUnmatched();
  }

  /// Adds the top level blocks in [childRange] for structure [index].
  void addBlock(int index, Interval childRange) {
    addSkewedChildren(index, structures[index], childRange);
  }

  /// Adds the [entity] from structure [index]. If the [entity] supports child
  /// entities, these are process individually. Otherwise the lines from
  /// [entity] are added directly.
  void addSkewedEntity(int index, OutputEntity entity) {
    if (entity.canHaveChildren) {
      handleSkew(index, entity.header);
      addSkewedChildren(index, entity, Interval(0, entity.children.length));
      handleSkew(index, entity.footer);
    } else {
      handleSkew(index, entity.interval, codeSourceFromEntities([entity]));
    }
  }

  /// Adds the children of [parent] in [childRange] from structure [index].
  void addSkewedChildren(int index, OutputEntity parent, Interval childRange) {
    for (int i = childRange.from; i < childRange.to; i++) {
      addSkewedEntity(index, parent.getChild(i));
    }
  }

  /// Adds the members of the [classes] aligned.
  void addMatchingContainers(List<OutputEntity> classes) {
    addLines(DiffKind.MATCHING, classes.map((c) => c.header).toList());
    align(
      classes[0].children,
      classes[1].children,
      match: (a, b) => a.name == b.name,
      handleSkew: (int listIndex, Interval childRange) {
        addSkewedChildren(listIndex, classes[listIndex], childRange);
      },
      handleMatched: (List<int> indices) {
        List<OutputEntity> entities = [
          classes[0].getChild(indices[0]),
          classes[1].getChild(indices[1]),
        ];
        if (entities.every((e) => e is Statics)) {
          addMatchingContainers(entities);
        } else {
          addLines(
            DiffKind.MATCHING,
            entities.map((e) => e.interval).toList(),
            codeSourceFromEntities(entities),
          );
        }
      },
      handleUnmatched: (List<int> indices) {
        List<Interval> intervals = [
          classes[0].getChild(indices[0]).interval,
          classes[1].getChild(indices[1]).interval,
        ];
        addLines(DiffKind.UNMATCHED, intervals);
      },
    );
    addLines(DiffKind.MATCHING, classes.map((c) => c.footer).toList());
  }

  /// Adds the library blocks in [indices] from the corresponding
  /// [OutputStructure]s, aligning their content.
  void addMatchingBlocks(List<int> indices) {
    List<OutputEntity> blocks = [
      structures[0].getChild(indices[0]),
      structures[1].getChild(indices[1]),
    ];

    addLines(DiffKind.MATCHING, blocks.map((b) => b.header).toList());
    align(
      blocks[0].children,
      blocks[1].children,
      match: (a, b) => a.name == b.name,
      handleSkew: (int listIndex, Interval childRange) {
        addSkewedChildren(listIndex, blocks[listIndex], childRange);
      },
      handleMatched: (List<int> indices) {
        List<OutputEntity> entities = [
          blocks[0].getChild(indices[0]),
          blocks[1].getChild(indices[1]),
        ];
        if (entities.every((e) => e is LibraryClass)) {
          addMatchingContainers(entities);
        } else {
          addLines(
            DiffKind.MATCHING,
            entities.map((e) => e.interval).toList(),
            codeSourceFromEntities(entities),
          );
        }
      },
      handleUnmatched: (List<int> indices) {
        List<Interval> intervals = [
          blocks[0].getChild(indices[0]).interval,
          blocks[1].getChild(indices[1]).interval,
        ];
        addLines(DiffKind.UNMATCHED, intervals);
      },
    );
    addLines(DiffKind.MATCHING, blocks.map((b) => b.footer).toList());
  }

  /// Adds the lines of the blocks in [indices] from the corresponding
  /// [OutputStructure]s.
  void addUnmatchedBlocks(List<int> indices) {
    List<OutputEntity> blocks = [
      structures[0].getChild(indices[0]),
      structures[1].getChild(indices[1]),
    ];
    addLines(DiffKind.UNMATCHED, [blocks[0].interval, blocks[1].interval]);
  }

  /// Computes the diff blocks for [OutputStructure]s.
  List<DiffBlock> computeBlocks() {
    addRaw(structures[0].header, structures[1].header);

    align(
      structures[0].children,
      structures[1].children,
      match: (a, b) => a.name == b.name,
      handleSkew: addBlock,
      handleMatched: addMatchingBlocks,
      handleUnmatched: addUnmatchedBlocks,
    );

    addRaw(structures[0].footer, structures[1].footer);

    return blocks;
  }

  /// Creates html lines for code lines in [codeSource]. The [sourceFileManager]
  /// is used to read that text from the source URIs.
  List<HtmlPart> codeLinesFromCodeSource(CodeSource codeSource) {
    List<HtmlPart> lines = <HtmlPart>[];
    SourceFile sourceFile = sourceFileManager.getSourceFile(codeSource.uri)!;
    String elementName = codeSource.name;
    HtmlLine line = HtmlLine();
    line.htmlParts.add(new ConstHtmlPart('<span class="comment">'));
    line.htmlParts.add(new HtmlText('${elementName}: ${sourceFile.filename}'));
    line.htmlParts.add(new ConstHtmlPart('</span>'));
    lines.add(line);
    if (codeSource.begin != null) {
      int startLine = sourceFile.getLocation(codeSource.begin!).line - 1;
      int endLine = sourceFile.getLocation(codeSource.end!).line;
      for (CodeLine codeLine in convertAnnotatedCodeToCodeLines(
        sourceFile.slowText(),
        const <Annotation>[],
        startLine: startLine,
        endLine: endLine,
      )) {
        codeLine.lineAnnotation = codeSource;
        lines.add(codeLine);
      }
    }
    return lines;
  }

  /// Creates a map from JavaScript [CodeLine]s in [jsCodeLines] to the Dart
  /// [CodeLine]s references in the source information.
  Map<CodeLine, List<CodeLine>> dartCodeLinesFromJsCodeLines(
    List<CodeLine> jsCodeLines,
  ) {
    Map<CodeLine, Interval> codeLineInterval = <CodeLine, Interval>{};
    Map<CodeLine, List<CodeLine>> jsToDartMap = <CodeLine, List<CodeLine>>{};
    List<Annotation> annotations = <Annotation>[];
    Uri? currentUri;
    late Interval interval;

    Map<Uri, Set<CodeSource>> codeSourceMap = <Uri, Set<CodeSource>>{};

    for (CodeLine jsCodeLine in jsCodeLines) {
      for (Annotation annotation in jsCodeLine.annotations) {
        CodeLineAnnotation codeLineAnnotation = annotation.data;
        for (CodeSource codeSource in codeLineAnnotation.codeSources) {
          codeSourceMap
              .putIfAbsent(codeSource.uri, () => Set<CodeSource>())
              .add(codeSource);
        }
      }
    }

    void flush() {
      if (currentUri == null) return;

      Set<CodeSource>? codeSources = codeSourceMap[currentUri];
      SourceFile sourceFile = sourceFileManager.getSourceFile(currentUri)!;
      List<CodeLine> annotatedDartCodeLines = convertAnnotatedCodeToCodeLines(
        sourceFile.slowText(),
        annotations,
        startLine: interval.from,
        endLine: interval.to,
        uri: currentUri,
      );
      if (codeSources != null) {
        CodeSource? currentCodeSource;
        late Interval currentLineInterval;
        for (CodeLine dartCodeLine in annotatedDartCodeLines) {
          if (currentCodeSource == null ||
              !currentLineInterval.contains(dartCodeLine.lineNo)) {
            currentCodeSource = null;
            for (CodeSource codeSource in codeSources) {
              Interval interval = Interval(
                sourceFile.getLocation(codeSource.begin!).line - 1,
                sourceFile.getLocation(codeSource.end!).line,
              );
              if (interval.contains(dartCodeLine.lineNo)) {
                currentCodeSource = codeSource;
                currentLineInterval = interval;
                break;
              }
            }
          }
          if (currentCodeSource != null) {
            dartCodeLine.lineAnnotation = currentCodeSource;
          }
        }
      }

      int index = 0;
      for (CodeLine jsCodeLine in codeLineInterval.keys) {
        List<CodeLine> dartCodeLines = jsToDartMap.putIfAbsent(
          jsCodeLine,
          () => <CodeLine>[],
        );
        if (dartCodeLines.isEmpty && index < annotatedDartCodeLines.length) {
          dartCodeLines.add(annotatedDartCodeLines[index++]);
        }
      }
      while (index < annotatedDartCodeLines.length) {
        jsToDartMap[codeLineInterval.keys.last]!.add(
          annotatedDartCodeLines[index++],
        );
      }

      currentUri = null;
    }

    void restart(CodeLine codeLine, CodeLocation codeLocation, int line) {
      flush();

      currentUri = codeLocation.uri;
      interval = Interval(line, line + 1);
      annotations = <Annotation>[];
      codeLineInterval.clear();
      codeLineInterval[codeLine] = interval;
    }

    for (CodeLine jsCodeLine in jsCodeLines) {
      for (Annotation annotation in jsCodeLine.annotations) {
        CodeLineAnnotation codeLineAnnotation = annotation.data;

        for (CodeLocation location in codeLineAnnotation.codeLocations) {
          SourceFile sourceFile = sourceFileManager.getSourceFile(
            location.uri,
          )!;
          int line = sourceFile.getLocation(location.offset).line - 1;
          if (currentUri != location.uri) {
            restart(jsCodeLine, location, line);
          } else if (interval.inWindow(line, windowSize: 2)) {
            interval = interval.include(line);
            codeLineInterval[jsCodeLine] = interval;
          } else {
            restart(jsCodeLine, location, line);
          }

          annotations.add(
            new Annotation(
              codeLineAnnotation.annotationType,
              location.offset,
              'id=${codeLineAnnotation.annotationId}',
              data: codeLineAnnotation,
            ),
          );
        }
      }
    }
    flush();
    return jsToDartMap;
  }
}

const DiffColumn column_js0 = const DiffColumn('js', 0);
const DiffColumn column_js1 = const DiffColumn('js', 1);
const DiffColumn column_dart = const DiffColumn('dart');

class ClassNames {
  static String column(DiffColumn column) => 'column_${column}';
  static String identical(bool alternate) =>
      'identical${alternate ? '1' : '2'}';
  static String corresponding(bool alternate) =>
      'corresponding${alternate ? '1' : '2'}';

  static const String buttons = 'buttons';
  static const String comment = 'comment';
  static const String header = 'header';
  static const String headerTable = 'header_table';
  static const String headerColumn = 'header_column';
  static const String legend = 'legend';
  static const String table = 'table';

  static const String cell = 'cell';
  static const String innerCell = 'inner_cell';

  static const String originalDart = 'main_dart';
  static const String inlinedDart = 'inlined_dart';

  static const String line = 'line';
  static const String lineNumber = 'line_number';
  static String colored(int index) => 'colored${index}';

  static const String withSourceInfo = 'with_source_info';
  static const String withoutSourceInfo = 'without_source_info';
  static const String additionalSourceInfo = 'additional_source_info';
  static const String unusedSourceInfo = 'unused_source_info';

  static const String sourceMapped = 'source_mapped';
  static const String sourceMapping = 'source_mapping';
  static String sourceMappingIndex(int index) => 'source_mapping${index}';

  static const String markers = 'markers';
  static const String marker = 'marker';
}

enum AnnotationType {
  withSourceInfo(ClassNames.withSourceInfo, true),
  withoutSourceInfo(ClassNames.withoutSourceInfo, false),
  additionalSourceInfo(ClassNames.additionalSourceInfo, true),
  unusedSourceInfo(ClassNames.unusedSourceInfo, false);

  final String className;
  final bool isSourceMapped;

  const AnnotationType(this.className, this.isSourceMapped);
}

class CodeLineAnnotation {
  final int annotationId;
  final AnnotationType annotationType;
  final List<CodeLocation> codeLocations;
  final List<CodeSource> codeSources;
  final String? stepInfo;
  int? sourceMappingIndex;

  CodeLineAnnotation({
    required this.annotationId,
    required this.annotationType,
    required this.codeLocations,
    required this.codeSources,
    this.stepInfo,
    this.sourceMappingIndex,
  });

  Map toJson(JsonStrategy strategy) {
    return {
      'annotationId': annotationId,
      'annotationType': annotationType.index,
      'codeLocations': codeLocations.map((l) => l.toJson(strategy)).toList(),
      'codeSources': codeSources.map((c) => c.toJson()).toList(),
      'stepInfo': stepInfo,
      'sourceMappingIndex': sourceMappingIndex,
    };
  }

  static fromJson(Map json, JsonStrategy strategy) {
    return CodeLineAnnotation(
      annotationId: json['id'],
      annotationType: AnnotationType.values[json['annotationType']],
      codeLocations: json['codeLocations']
          .map((j) => CodeLocation.fromJson(j, strategy))
          .toList(),
      codeSources: json['codeSources']
          .map((j) => CodeSource.fromJson(j))
          .toList(),
      stepInfo: json['stepInfo'],
      sourceMappingIndex: json['sourceMappingIndex'],
    );
  }
}
