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

import com.android.tools.r8.logging.Log;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Range;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.MemberNaming.SingleLineRange;
import com.google.common.collect.ImmutableMap;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * Parses a Proguard mapping file and produces mappings from obfuscated class names to the original
 * name and from obfuscated member signatures to the original members the obfuscated member
 * was formed of.
 * <p>
 * The expected format is as follows
 * <p>
 * original-type-name ARROW obfuscated-type-name COLON starts a class mapping
 * description and maps original to obfuscated.
 * <p>
 * followed by one or more of
 * <p>
 * signature ARROW name
 * <p>
 * which maps the member with the given signature to the new name. This mapping is not
 * bidirectional as member names are overloaded by signature. To make it bidirectional, we extend
 * the name with the signature of the original member.
 * <p>
 * Due to inlining, we might have the above prefixed with a range (two numbers separated by :).
 * <p>
 * range COLON signature ARROW name
 * <p>
 * This has the same meaning as the above but also encodes the line number range of the member. This
 * may be followed by multiple inline mappings of the form
 * <p>
 * range COLON signature COLON range ARROW name
 * <p>
 * to identify that signature was inlined from the second range to the new line numbers in the first
 * range. This is then followed by information on the call trace to where the member was inlined.
 * These entries have the form
 * <p>
 * range COLON signature COLON number ARROW name
 * <p>
 * and are currently only stored to be able to reproduce them later.
 */
public class ProguardMapReader implements AutoCloseable {

  private final BufferedReader reader;

  public void close() throws IOException {
    if (reader != null) {
      reader.close();
    }
  }

  private ProguardMapReader(BufferedReader reader) throws IOException {
    this.reader = reader;
  }

  public static ClassNameMapper mapperFromInputStream(InputStream in) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF8"));
    try (ProguardMapReader proguardReader = new ProguardMapReader(reader)) {
      return proguardReader.parse();
    }
  }

  public static ClassNameMapper mapperFromFile(Path path) throws IOException {
    return mapperFromInputStream(Files.newInputStream(path));
  }

  public static ClassNameMapper mapperFromString(String contents) throws IOException {
    return mapperFromInputStream(
        new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)));
  }

  // Internal parser state
  private int lineNo = 0;
  private int lineOffset = 0;
  private String line;

  private char peek() {
    return peek(0);
  }

  private char peek(int distance) {
    return lineOffset + distance < line.length()
        ? line.charAt(lineOffset + distance)
        : '\n';
  }

  private char next() {
    try {
      return line.charAt(lineOffset++);
    } catch (ArrayIndexOutOfBoundsException e) {
      throw new ParseException("Unexpected end of line");
    }
  }

  private boolean nextLine() throws IOException {
    if (line.length() != lineOffset) {
      throw new ParseException("Expected end of line");
    }
    return skipLine();
  }

  private boolean skipLine() throws IOException {
    lineNo++;
    lineOffset = 0;
    line = reader.readLine();
    return hasLine();
  }

  private boolean hasLine() {
    return line != null;
  }

  // Helpers for common pattern
  private void skipWhitespace() {
    while (Character.isWhitespace(peek())) {
      next();
    }
  }

  private char expect(char c) {
    if (next() != c) {
      throw new ParseException("Expected '" + c + "'");
    }
    return c;
  }

  public ClassNameMapper parse() throws IOException {
    // Read the first line.
    line = reader.readLine();
    Map<String, ClassNaming> classNames = parseClassMappings();
    return new ClassNameMapper(classNames);
  }

  // Parsing of entries

  private Map<String, ClassNaming> parseClassMappings() throws IOException {
    ImmutableMap.Builder<String, ClassNaming> builder = ImmutableMap.builder();
    while (hasLine()) {
      String before = parseType(false);
      skipWhitespace();
      // Workaround for proguard map files that contain entries for package-info.java files.
      if (!acceptArrow()) {
        // If this was a package-info line, we parsed the "package" string.
        if (!before.endsWith("package") || !acceptString("-info")) {
          throw new ParseException("Expected arrow after class name " + before);
        }
        skipLine();
        continue;
      }
      skipWhitespace();
      String after = parseType(false);
      expect(':');
      ClassNaming currentClass = new ClassNaming(after, before);
      builder.put(after, currentClass);
      if (nextLine()) {
        parseMemberMappings(currentClass);
      }
    }
    return builder.build();
  }

  private void parseMemberMappings(ClassNaming currentClass) throws IOException {
    MemberNaming current = null;
    Range previousInlineRange = null;
    Signature previousSignature = null;
    String previousRenamedName = null;
    List<Consumer<MemberNaming>> collectedInfos = new ArrayList<>(10);

    while (Character.isWhitespace(peek())) {
      skipWhitespace();
      Range inlinedLineRange = maybeParseRange();
      if (inlinedLineRange != null) {
        expect(':');
      }
      Signature signature = parseSignature();
      Range originalLineRange;
      if (peek() == ':') {
        // This is an inlining definition
        next();
        originalLineRange = maybeParseRange();
        if (originalLineRange == null) {
          if (!skipLine()) {
            break;
          }
          continue;
        }
      } else {
        originalLineRange = null;
      }
      skipWhitespace();
      skipArrow();
      skipWhitespace();
      String renamedName = parseMethodName();
      // If there is no line number information at the front or if it changes, we have a new
      // segment. Likewise, if the range information on the right hand side has two values, we have
      // a new segment.
      if (inlinedLineRange == null
          || previousInlineRange == null
          || originalLineRange == null
          || !previousInlineRange.equals(inlinedLineRange)
          || !originalLineRange.isSingle()) {
        // We are at a range boundary. Either we parsed something new, or an inline frame is over.
        // We detect this by checking whether the previous signature matches the one of current.
        if (current == null || !previousSignature.equals(current.signature)) {
          if (collectedInfos.size() == 1) {
            current = new MemberNaming(previousSignature, previousRenamedName, previousInlineRange);
            currentClass.addMemberEntry(current);
          } else {
            if (Log.ENABLED && !collectedInfos.isEmpty()) {
              Log.warn(getClass(),
                  "More than one member entry that forms a new group at %s %s -> %s",
                  previousInlineRange, previousSignature, previousRenamedName);
            }
          }
        } else {
          MemberNaming finalCurrent = current;
          collectedInfos.forEach(info -> info.accept(finalCurrent));
        }
        collectedInfos.clear();
      }
      // Defer the creation of the info until we have the correct member.
      collectedInfos.add((m) -> m.addInliningRange(inlinedLineRange, signature, originalLineRange));
      // We have parsed the whole line, move on.
      previousInlineRange = inlinedLineRange;
      previousSignature = signature;
      previousRenamedName = renamedName;
      if (!nextLine()) {
        break;
      }
    }
    // Process the last round if lines have been read.
    if (current == null || !previousSignature.equals(current.signature)) {
      if (collectedInfos.size() == 1) {
        current = new MemberNaming(previousSignature, previousRenamedName, previousInlineRange);
        currentClass.addMemberEntry(current);
      }
    } else {
      MemberNaming finalCurrent = current;
      collectedInfos.forEach(info -> info.accept(finalCurrent));
    }
    collectedInfos.clear();
  }

  // Parsing of components

  private void skipIdentifier(boolean allowInit) {
    boolean isInit = false;
    if (allowInit && peek() == '<') {
      // swallow the leading < character
      next();
      isInit = true;
    }
    if (!Character.isJavaIdentifierStart(peek())) {
      throw new ParseException("Identifier expected");
    }
    next();
    while (Character.isJavaIdentifierPart(peek())) {
      next();
    }
    if (isInit) {
      expect('>');
    }
    if (Character.isJavaIdentifierPart(peek())) {
      throw new ParseException("End of identifier expected");
    }
  }

  // Cache for canonicalizing strings.
  // This saves 10% of heap space for large programs.
  final HashMap<String, String> cache = new HashMap<>();

  private String substring(int start) {
    String result = line.substring(start, lineOffset);
    if (cache.containsKey(result)) {
      return cache.get(result);
    }
    cache.put(result, result);
    return result;
  }

  private String parseMethodName() {
    int startPosition = lineOffset;
    skipIdentifier(true);
    while (peek() == '.') {
      next();
      skipIdentifier(true);
    }
    return substring(startPosition);
  }

  private String parseType(boolean allowArray) {
    int startPosition = lineOffset;
    skipIdentifier(false);
    while (peek() == '.') {
      next();
      skipIdentifier(false);
    }
    if (allowArray) {
      while (peek() == '[') {
        next();
        expect(']');
      }
    }
    return substring(startPosition);
  }

  private Signature parseSignature() {
    String type = parseType(true);
    expect(' ');
    String name = parseMethodName();
    Signature signature;
    if (peek() == '(') {
      next();
      String[] arguments;
      if (peek() == ')') {
        arguments = new String[0];
      } else {
        List<String> items = new LinkedList<>();
        items.add(parseType(true));
        while (peek() != ')') {
          expect(',');
          items.add(parseType(true));
        }
        arguments = items.toArray(new String[items.size()]);
      }
      expect(')');
      signature = new MethodSignature(name, type, arguments);
    } else {
      signature = new FieldSignature(name, type);
    }
    return signature;
  }

  private void skipArrow() {
    expect('-');
    expect('>');
  }

  private boolean acceptArrow() {
    if (peek() == '-' && peek(1) == '>') {
      next();
      next();
      return true;
    }
    return false;
  }

  private boolean acceptString(String s) {
    for (int i = 0; i < s.length(); i++) {
      if (peek(i) != s.charAt(i)) {
        return false;
      }
    }
    for (int i = 0; i < s.length(); i++) {
      next();
    }
    return true;
  }

  private Range maybeParseRange() {
    if (!Character.isDigit(peek())) {
      return null;
    }
    int from = parseNumber();
    if (peek() != ':') {
      return new SingleLineRange(from);
    }
    expect(':');
    int to = parseNumber();
    return new Range(from, to);
  }

  private int parseNumber() {
    int result = 0;
    if (!Character.isDigit(peek())) {
      throw new ParseException("Number expected");
    }
    do {
      result *= 10;
      result += Character.getNumericValue(next());
    } while (Character.isDigit(peek()));
    return result;
  }

  private class ParseException extends RuntimeException {

    private final int lineNo;
    private final int lineOffset;
    private final String msg;

    ParseException(String msg) {
      lineNo = ProguardMapReader.this.lineNo;
      lineOffset = ProguardMapReader.this.lineOffset;
      this.msg = msg;
    }

    public String toString() {
      return "Parse error [" + lineNo + ":" + lineOffset + "] " + msg;
    }
  }
}
