// 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.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;
        switch (identifiers.length) {
          case 0:
            identifier = NO_LIBRARY_DESUGARING;
            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()) {
          desugaredLibraryIdentifiers.add(identifier);
        } else {
          assert 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() ? "dex" : "cf";
    }
    return jsonObject.get(BACKEND).getAsString();
  }

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

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