// 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.graph.DexString;
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.Map.Entry;

/**
 * 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 SHA1 = "sha-1";
  public static final String COMPILATION_MODE = "compilation-mode";

  public enum Tool {D8, R8}

  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 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 Tool getTool() {
    return tool;
  }

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

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

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

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

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

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