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

// @dart = 2.7

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

/// 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),
    void handleSkew(int listIndex, Interval range),
    void handleMatched(List<int> indices),
    void handleUnmatched(List<int> indices)}) {
  if (match == null) {
    match = (a, b) => a == b;
  }

  if (range1 == null) {
    range1 = new Interval(0, list1.length);
  }
  if (range2 == null) {
    range2 = new 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 new 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 = new Interval(start1, end1);
      Interval subrange2 = new 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, new Interval(start1, element1inList2.from));
          start1 = element1inList2.from;
          break;
        case ALIGN2:
          handleSkew(1, new Interval(start2, element2inList1.from));
          start2 = element2inList1.from;
          break;
        case UNMATCHED:
          handleUnmatched([start1++, start2++]);
          break;
      }
    }
  }
  if (start1 < end1) {
    handleSkew(0, new Interval(start1, end1));
  }
  if (start2 < end2) {
    handleSkew(1, new 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 new 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 = new 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 new 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 = new Set<CodeSource>();
    codeSources.addAll(mainCodeSources);

    DiffBlock block = new 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),
        new 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 = new Set<CodeSource>();
    codeSources.addAll(mainCodeSources);

    DiffBlock block = new 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),
          new 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 [
          new Interval(indices[0], indices[0] + 1),
          new Interval(indices[1], indices[1] + 1)
        ];
      } else {
        current[0] = new Interval(current[0].from, indices[0] + 1);
        current[1] = new 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, new 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<BasicEntity> 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<LibraryBlock> 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<BasicEntity> 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<LibraryBlock> 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 = new 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;
    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, () => new 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;
        Interval currentLineInterval;
        for (CodeLine dartCodeLine in annotatedDartCodeLines) {
          if (currentCodeSource == null ||
              !currentLineInterval.contains(dartCodeLine.lineNo)) {
            currentCodeSource = null;
            for (CodeSource codeSource in codeSources) {
              Interval interval = new 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 = new 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';
}

class AnnotationType {
  static const WITH_SOURCE_INFO =
      const AnnotationType(0, ClassNames.withSourceInfo, true);
  static const WITHOUT_SOURCE_INFO =
      const AnnotationType(1, ClassNames.withoutSourceInfo, false);
  static const ADDITIONAL_SOURCE_INFO =
      const AnnotationType(2, ClassNames.additionalSourceInfo, true);
  static const UNUSED_SOURCE_INFO =
      const AnnotationType(3, ClassNames.unusedSourceInfo, false);

  final int index;
  final String className;
  final bool isSourceMapped;

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

  static const List<AnnotationType> values = const <AnnotationType>[
    WITH_SOURCE_INFO,
    WITHOUT_SOURCE_INFO,
    ADDITIONAL_SOURCE_INFO,
    UNUSED_SOURCE_INFO
  ];
}

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

  CodeLineAnnotation(
      {this.annotationId,
      this.annotationType,
      this.codeLocations,
      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 new 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']);
  }
}
