// Copyright (c) 2017, the Rex 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.dex;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.errors.DesugaredLibraryMismatchDiagnostic;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;

/** Abstraction for hidden dex marker intended for the main dex file. */
public class Marker {

  public static final String VERSION = "version";
  public static final String MIN_API = "min-api";
  public static final String DESUGARED_LIBRARY_IDENTIFIERS = "desugared-library-identifiers";
  public static final String SHA1 = "sha-1";
  public static final String COMPILATION_MODE = "compilation-mode";
  public static final String HAS_CHECKSUMS = "has-checksums";
  public static final String BACKEND = "backend";
  public static final String PG_MAP_ID = "pg-map-id";
  public static final String R8_MODE = "r8-mode";
  private static final String NO_LIBRARY_DESUGARING = "<no-library-desugaring>";

  public enum Tool {
    D8,
    R8,
    L8,
    Relocator;

    public static Tool[] valuesR8andD8() {
      return new Tool[] {Tool.D8, Tool.R8};
    }
  }

  public enum Backend {
    CF,
    DEX
  }

  private static final char PREFIX_CHAR = '~';
  private static final String PREFIX = "~~";
  private static final String D8_PREFIX = PREFIX + Tool.D8 + "{";
  private static final String R8_PREFIX = PREFIX + Tool.R8 + "{";
  private static final String L8_PREFIX = PREFIX + Tool.L8 + "{";

  private final JsonObject jsonObject;
  private final Tool tool;

  public Marker(Tool tool) {
    this(tool, new JsonObject());
  }

  private Marker(Tool tool, JsonObject jsonObject) {
    this.tool = tool;
    this.jsonObject = jsonObject;
  }

  public static void checkCompatibleDesugaredLibrary(Set<Marker> markers, Reporter reporter) {
    if (markers.size() <= 1) {
      return;
    }
    // In L8 compilation, the compilation has two markers, a L8 marker, which has a desugared
    // library property, and either a D8 or a R8 marker, which has no desugared library property.
    // In other compilations, the desugared library versions have to be consistent.
    Set<String> desugaredLibraryIdentifiers = new HashSet<>();
    for (Marker marker : markers) {
      if (marker.tool == Tool.L8) {
        assert marker.getDesugaredLibraryIdentifiers().length > 0;
        assert markers.stream()
            .allMatch(m -> m.tool == Tool.L8 || m.getDesugaredLibraryIdentifiers().length == 0);
      } else {
        String[] identifiers = marker.getDesugaredLibraryIdentifiers();
        String identifier = null;
        switch (identifiers.length) {
          case 0:
            // Only add the <no-library-desugaring> identifier for DEX. A marker from CF is
            // assumed to go though desugaring for compiling to DEX, and that will introduce the
            // DEX marker with the final library desugaring identifier.
            if (marker.isDexBackend()) {
              identifier = NO_LIBRARY_DESUGARING;
            } else {
              assert marker.isCfBackend();
            }
            break;
          case 1:
            identifier = identifiers[0];
            break;
          default:
            // To be implemented once D8/R8 compilation supports multiple desugared libraries.
            throw reporter.fatalError(
                new StringDiagnostic(
                    "Merging program compiled with multiple desugared libraries."));
        }
        if (marker.isDesugared() && identifier != null) {
          desugaredLibraryIdentifiers.add(identifier);
        } else {
          assert identifier == null || identifier.equals(NO_LIBRARY_DESUGARING);
        }
      }
    }

    if (desugaredLibraryIdentifiers.size() > 1) {
      reporter.error(new DesugaredLibraryMismatchDiagnostic(desugaredLibraryIdentifiers, markers));
    }
  }

  public Tool getTool() {
    return tool;
  }

  public boolean isD8() {
    return tool == Tool.D8;
  }

  public boolean isR8() {
    return tool == Tool.R8;
  }

  public boolean isL8() {
    return tool == Tool.L8;
  }

  public boolean isRelocator() {
    return tool == Tool.Relocator;
  }

  public String getVersion() {
    return jsonObject.get(VERSION).getAsString();
  }

  public Marker setVersion(String version) {
    assert !jsonObject.has(VERSION);
    jsonObject.addProperty(VERSION, version);
    return this;
  }

  public boolean isDesugared() {
    // For both DEX and CF output from D8 and R8 a min-api setting implies that the code has been
    // desugared, as even the highest min-api require desugaring of lambdas.
    return hasMinApi();
  }

  public boolean hasMinApi() {
    return jsonObject.has(MIN_API);
  }

  public Long getMinApi() {
    return jsonObject.get(MIN_API).getAsLong();
  }

  public Marker setMinApi(long minApi) {
    assert !jsonObject.has(MIN_API);
    jsonObject.addProperty(MIN_API, minApi);
    return this;
  }

  public boolean hasDesugaredLibraryIdentifiers() {
    return jsonObject.has(DESUGARED_LIBRARY_IDENTIFIERS);
  }

  public String[] getDesugaredLibraryIdentifiers() {
    if (jsonObject.has(DESUGARED_LIBRARY_IDENTIFIERS)) {
      JsonArray array = jsonObject.get(DESUGARED_LIBRARY_IDENTIFIERS).getAsJsonArray();
      String[] identifiers = new String[array.size()];
      for (int i = 0; i < array.size(); i++) {
        identifiers[i] = array.get(i).getAsString();
      }
      return identifiers;
    }
    return new String[0];
  }

  public Marker setDesugaredLibraryIdentifiers(String... identifiers) {
    assert !jsonObject.has(DESUGARED_LIBRARY_IDENTIFIERS);
    JsonArray jsonIdentifiers = new JsonArray();
    for (String identifier : identifiers) {
      jsonIdentifiers.add(identifier);
    }
    jsonObject.add(DESUGARED_LIBRARY_IDENTIFIERS, jsonIdentifiers);
    return this;
  }

  public String getSha1() {
    return jsonObject.get(SHA1).getAsString();
  }

  public Marker setSha1(String sha1) {
    assert !jsonObject.has(SHA1);
    jsonObject.addProperty(SHA1, sha1);
    return this;
  }

  public String getCompilationMode() {
    return jsonObject.get(COMPILATION_MODE).getAsString();
  }

  public Marker setCompilationMode(CompilationMode mode) {
    assert !jsonObject.has(COMPILATION_MODE);
    jsonObject.addProperty(COMPILATION_MODE, mode.toString().toLowerCase());
    return this;
  }

  public boolean hasBackend() {
    return jsonObject.has(BACKEND);
  }

  public String getBackend() {
    if (!hasBackend()) {
      // Before adding backend we would always compile to dex if min-api was specified.
      return hasMinApi() ? Backend.DEX.name().toLowerCase() : Backend.CF.name().toLowerCase();
    }
    return jsonObject.get(BACKEND).getAsString();
  }

  public boolean isCfBackend() {
    return getBackend().equals(Backend.CF.name().toLowerCase());
  }

  public boolean isDexBackend() {
    return getBackend().equals(Backend.DEX.name().toLowerCase());
  }

  public Marker setBackend(Backend backend) {
    assert !hasBackend();
    jsonObject.addProperty(BACKEND, backend.name().toLowerCase());
    return this;
  }

  public boolean getHasChecksums() {
    return jsonObject.get(HAS_CHECKSUMS).getAsBoolean();
  }

  public Marker setHasChecksums(boolean hasChecksums) {
    assert !jsonObject.has(HAS_CHECKSUMS);
    jsonObject.addProperty(HAS_CHECKSUMS, hasChecksums);
    return this;
  }

  public String getPgMapId() {
    return jsonObject.get(PG_MAP_ID).getAsString();
  }

  public Marker setPgMapId(String pgMapId) {
    assert !jsonObject.has(PG_MAP_ID);
    jsonObject.addProperty(PG_MAP_ID, pgMapId);
    return this;
  }

  public String getR8Mode() {
    return jsonObject.get(R8_MODE).getAsString();
  }

  public Marker setR8Mode(String r8Mode) {
    assert !jsonObject.has(R8_MODE);
    jsonObject.addProperty(R8_MODE, r8Mode);
    return this;
  }

  @Override
  public String toString() {
    // In order to make printing of markers deterministic we sort the entries by key.
    final JsonObject sortedJson = new JsonObject();
    jsonObject.entrySet().stream()
        .sorted(Comparator.comparing(Entry::getKey))
        .forEach(entry -> sortedJson.add(entry.getKey(), entry.getValue()));
    return PREFIX + tool + sortedJson;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Marker) {
      Marker other = (Marker) obj;
      return (tool == other.tool) && jsonObject.equals(other.jsonObject);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return tool.hashCode() + 3 * jsonObject.hashCode();
  }

  public DexString toDexString(DexItemFactory factory) {
    return factory.createString(toString());
  }

  // Try to parse str as a marker.
  // Returns null if parsing fails.
  public static Marker parse(DexString dexString) {
    if (dexString.size > 2
        && dexString.content[0] == PREFIX_CHAR
        && dexString.content[1] == PREFIX_CHAR) {
      String str = dexString.toString();
      if (str.startsWith(D8_PREFIX)) {
        return internalParse(Tool.D8, str.substring(D8_PREFIX.length() - 1));
      }
      if (str.startsWith(R8_PREFIX)) {
        return internalParse(Tool.R8, str.substring(R8_PREFIX.length() - 1));
      }
      if (str.startsWith(L8_PREFIX)) {
        return internalParse(Tool.L8, str.substring(L8_PREFIX.length() - 1));
      }
    }
    return null;
  }

  private static Marker internalParse(Tool tool, String str) {
    try {
      JsonElement result = new JsonParser().parse(str);
      if (result.isJsonObject()) {
        return new Marker(tool, result.getAsJsonObject());
      }
    } catch (JsonSyntaxException e) {
      // Fall through.
    }
    return null;
  }
}
