// Copyright (c) 2019, the R8 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.

package com.android.tools.r8.kotlin;

import com.android.tools.r8.naming.Range;
import com.android.tools.r8.utils.SegmentTree;
import com.android.tools.r8.utils.ThrowingConsumer;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

// This is a parser for the Kotlin-generated source debug extensions, which is a stratified map.
// The kotlin-parser for this data is can be found here in the kotlin compiler:
// compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SMAPParser.kt
public class KotlinSourceDebugExtensionParser {

  private static final String SMAP_IDENTIFIER = "SMAP";
  private static final String SMAP_SECTION_START = "*S";
  private static final String SMAP_SECTION_KOTLIN_START = SMAP_SECTION_START + " Kotlin";
  private static final String SMAP_FILES_IDENTIFIER = "*F";
  private static final String SMAP_LINES_IDENTIFIER = "*L";
  private static final String SMAP_END_IDENTIFIER = "*E";

  public static class KotlinSourceDebugExtensionParserException extends Exception {

    KotlinSourceDebugExtensionParserException(String message) {
      super(message);
    }
  }

  public static class BufferedStringReader implements Closeable {

    private final BufferedReader reader;

    private String readLine;

    BufferedStringReader(String data) {
      reader = new BufferedReader(new StringReader(data));
    }

    String readNextLine() throws IOException {
      return readLine = reader.readLine();
    }

    boolean readExpectedLine(String expected) throws IOException {
      return readNextLine().equals(expected);
    }

    void readExpectedLineOrThrow(String expected)
        throws KotlinSourceDebugExtensionParserException, IOException {
      if (!readExpectedLine(expected)) {
        throw new KotlinSourceDebugExtensionParserException(
            "The string " + readLine + " does not match the expected string " + expected);
      }
    }

    boolean isEOF() {
      return readLine == null;
    }

    BufferedStringReader readUntil(String terminator) throws IOException {
      while (!terminator.equals(readLine) && !isEOF()) {
        readNextLine();
      }
      if (isEOF()) {
        return this;
      }
      return this;
    }

    void readUntil(
        String terminator,
        int linesInBlock,
        ThrowingConsumer<List<String>, KotlinSourceDebugExtensionParserException> callback)
        throws IOException, KotlinSourceDebugExtensionParserException {
      readUntil(terminator::equals, linesInBlock, callback);
    }

    void readUntil(
        Predicate<String> terminator,
        int linesInBlock,
        ThrowingConsumer<List<String>, KotlinSourceDebugExtensionParserException> callback)
        throws IOException, KotlinSourceDebugExtensionParserException {
      if (terminator.test(readLine)) {
        return;
      }
      List<String> readStrings = new ArrayList<>();
      readStrings.add(readNextLine());
      int linesLeft = linesInBlock;
      while (!terminator.test(readLine) && !isEOF()) {
        if (linesLeft == 1) {
          assert readStrings.size() == linesInBlock;
          callback.accept(readStrings);
          linesLeft = linesInBlock;
          readStrings = new ArrayList<>();
        } else {
          linesLeft -= 1;
        }
        readStrings.add(readNextLine());
      }
      if (readStrings.size() > 0 && !terminator.test(readStrings.get(0))) {
        throw new KotlinSourceDebugExtensionParserException(
            "Block size does not match linesInBlock = " + linesInBlock);
      }
    }

    @Override
    public void close() throws IOException {
      reader.close();
    }
  }

  public static Result parse(String annotationData) {
    if (annotationData == null || annotationData.isEmpty()) {
      return null;
    }

    // The source debug smap data is on the following form:
    // SMAP
    // <filename>
    // Kotlin <-- why is this even here?
    // *S <section>
    // *F
    // + <file_id_i> <file_name_i>
    // <path_i>
    // *L
    // <from>#<file>,<to>:<debug-line-position>
    // <from>#<file>:<debug-line-position>
    // *E <-- This is an error in versions prior to kotlin 1.5 and is not present in kotlin 1.5.
    // *S KotlinDebug
    // ***
    // *E
    try (BufferedStringReader reader = new BufferedStringReader(annotationData)) {
      ResultBuilder builder = new ResultBuilder();
      // Check for SMAP
      if (!reader.readExpectedLine(SMAP_IDENTIFIER)) {
        return null;
      }
      if (reader.readUntil(SMAP_SECTION_KOTLIN_START).isEOF()) {
        return null;
      }
      // At this point we should be parsing a kotlin source debug extension, so we will throw if we
      // read an unexpected line.
      reader.readExpectedLineOrThrow(SMAP_FILES_IDENTIFIER);
      // Iterate over the files section with the format:
      // + <file_number_i> <file_name_i>
      // <file_path_i>
      reader.readUntil(
          SMAP_LINES_IDENTIFIER, 2, block -> addFileToBuilder(block.get(0), block.get(1), builder));

      // Ensure that we read *L.
      if (reader.isEOF()) {
        throw new KotlinSourceDebugExtensionParserException(
            "Unexpected EOF - no debug line positions");
      }
      // Iterate over the debug line number positions:
      // <from>#<file>,<range>:<debug-line-position>
      // or
      // <from>#<file>:<debug-line-position>
      reader.readUntil(
          line -> line.equals(SMAP_END_IDENTIFIER) || line.startsWith(SMAP_SECTION_START),
          1,
          block -> addDebugEntryToBuilder(block.get(0), builder));

      // Ensure that we read the end section and it is terminated.
      if (reader.isEOF() && !reader.readLine.equals(SMAP_END_IDENTIFIER)) {
        throw new KotlinSourceDebugExtensionParserException(
            "Unexpected EOF when parsing SMAP debug entries");
      }

      return builder.build();
    } catch (IOException | KotlinSourceDebugExtensionParserException e) {
      return null;
    }
  }

  private static void addFileToBuilder(String entryLine, String filePath, ResultBuilder builder)
      throws KotlinSourceDebugExtensionParserException {
    // + <file_number_i> <file_name_i>
    // <file_path_i>
    String[] entries = entryLine.trim().split(" ");
    if (entries.length != 3 || !entries[0].equals("+")) {
      throw new KotlinSourceDebugExtensionParserException(
          "Wrong number of entries on line " + entryLine);
    }
    String fileName = entries[2];
    if (fileName.isEmpty()) {
      throw new KotlinSourceDebugExtensionParserException(
          "Did not expect file name to be empty for line " + entryLine);
    }
    if (filePath == null || filePath.isEmpty()) {
      throw new KotlinSourceDebugExtensionParserException(
          "Did not expect file path to be null or empty for " + entryLine);
    }
    int index = asInteger(entries[1]);
    Source source = new Source(fileName, filePath);
    Source existingSource = builder.files.put(index, source);
    if (existingSource != null) {
      throw new KotlinSourceDebugExtensionParserException(
          "File index " + index + " was already mapped to an existing source: " + source);
    }
  }

  private static int asInteger(String numberAsString)
      throws KotlinSourceDebugExtensionParserException {
    int number = -1;
    try {
      number = Integer.parseInt(numberAsString);
    } catch (NumberFormatException e) {
      throw new KotlinSourceDebugExtensionParserException(
          "Could not parse number " + numberAsString);
    }
    return number;
  }

  private static void addDebugEntryToBuilder(String debugEntry, ResultBuilder builder)
      throws KotlinSourceDebugExtensionParserException {
    // <from>#<file>,<size>:<debug-line-position>
    // or
    // <from>#<file>:<debug-line-position>
    // All positions should define intervals for mappings.
    try {
      int targetSplit = debugEntry.indexOf(':');
      int target = Integer.parseInt(debugEntry.substring(targetSplit + 1));
      String original = debugEntry.substring(0, targetSplit);
      int fileIndexSplit = original.indexOf('#');
      int originalStart = Integer.parseInt(original.substring(0, fileIndexSplit));
      // The range may have a different end than start.
      String fileAndEndRange = original.substring(fileIndexSplit + 1);
      int endRangeCharPosition = fileAndEndRange.indexOf(',');
      int size = 1;
      if (endRangeCharPosition > -1) {
        // The file should be at least one number wide.
        assert endRangeCharPosition > 0;
        size = Integer.parseInt(fileAndEndRange.substring(endRangeCharPosition + 1));
      } else {
        endRangeCharPosition = fileAndEndRange.length();
      }
      int fileIndex = Integer.parseInt(fileAndEndRange.substring(0, endRangeCharPosition));
      Source thisFileSource = builder.files.get(fileIndex);
      if (thisFileSource == null) {
        throw new KotlinSourceDebugExtensionParserException(
            "Could not find file with index " + fileIndex);
      }
      Range range = new Range(originalStart, originalStart + (size - 1));
      Position position = new Position(thisFileSource, range);
      builder.segmentTree.add(target, target + (size - 1), position);
    } catch (NumberFormatException e) {
      throw new KotlinSourceDebugExtensionParserException("Could not convert position to number");
    }
  }

  public static class Result {

    private final SegmentTree<Position> segmentTree;

    public Result(SegmentTree<Position> segmentTree) {
      this.segmentTree = segmentTree;
    }

    public Map.Entry<Integer, Position> lookup(int point) {
      return segmentTree.findEntry(point);
    }

    public int size() {
      return segmentTree.size();
    }
  }

  public static class ResultBuilder {

    SegmentTree<Position> segmentTree = new SegmentTree<>(false);
    Map<Integer, Source> files = new HashMap<>();

    public Result build() {
      return new Result(segmentTree);
    }
  }

  public static class Source {
    private final String fileName;
    private final String path;

    private Source(String fileName, String path) {
      this.fileName = fileName;
      this.path = path;
    }

    public String getFileName() {
      return fileName;
    }

    public String getPath() {
      return path;
    }

    @Override
    public String toString() {
      return path + "(" + fileName + ")";
    }
  }

  public static class Position {
    private final Source source;
    private final Range range;

    public Position(Source source, Range range) {
      this.source = source;
      this.range = range;
    }

    public Source getSource() {
      return source;
    }

    public Range getRange() {
      return range;
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append(range.from);
      sb.append("#");
      sb.append(source);
      if (range.to != range.from) {
        sb.append(",");
        sb.append(range.to);
      }
      sb.append(":");
      return sb.toString();
    }
  }
}
