// 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'],
    );
  }
}
