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

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.dex.Marker.Backend;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.features.FeatureSplitConfiguration;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.startup.StartupProfileProvider;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class DumpOptions {

  // The following keys and values should not be changed to keep the dump utility backward
  // compatible with previous versions. They are also used by the python script compileDump and
  // the corresponding CompileDumpCompatR8 java class.
  private static final String BACKEND_KEY = "backend";
  private static final String TOOL_KEY = "tool";
  private static final String MODE_KEY = "mode";
  private static final String DEBUG_MODE_VALUE = "debug";
  private static final String RELEASE_MODE_VALUE = "release";
  private static final String MIN_API_KEY = "min-api";
  private static final String OPTIMIZE_MULTIDEX_FOR_LINEAR_ALLOC_KEY =
      "optimize-multidex-for-linear-alloc";
  private static final String THREAD_COUNT_KEY = "thread-count";
  private static final String DESUGAR_STATE_KEY = "desugar-state";
  private static final String INTERMEDIATE_KEY = "intermediate";
  private static final String INCLUDE_DATA_RESOURCES_KEY = "include-data-resources";
  private static final String TREE_SHAKING_KEY = "tree-shaking";
  private static final String MINIFICATION_KEY = "minification";
  private static final String FORCE_PROGUARD_COMPATIBILITY_KEY = "force-proguard-compatibility";
  public static final String SYSTEM_PROPERTY_PREFIX = "system-property-";
  private static final String ENABLE_MISSING_LIBRARY_API_MODELING =
      "enable-missing-library-api-modeling";
  private static final String ANDROID_PLATFORM_BUILD = "android-platform-build";
  private static final String TRACE_REFERENCES_CONSUMER = "trace_references_consumer";

  private final Backend backend;
  private final Tool tool;
  private final CompilationMode compilationMode;
  private final int minApi;
  private final boolean optimizeMultidexForLinearAlloc;
  private final int threadCount;
  private final DesugarState desugarState;
  private final Optional<Boolean> intermediate;
  private final Optional<Boolean> includeDataResources;
  private final Optional<Boolean> treeShaking;
  private final Optional<Boolean> minification;
  private final Optional<Boolean> forceProguardCompatibility;

  // Dump if present.
  private final DesugaredLibrarySpecification desugaredLibrarySpecification;
  private final FeatureSplitConfiguration featureSplitConfiguration;
  private final ProguardConfiguration proguardConfiguration;
  private final List<ProguardConfigurationRule> mainDexKeepRules;
  private final Collection<StartupProfileProvider> startupProfileProviders;
  private final boolean enableMissingLibraryApiModeling;
  private final boolean isAndroidPlatformBuild;

  private final Map<String, String> systemProperties;

  // TraceReferences only.
  private final String traceReferencesConsumer;

  // Reporting only.
  private final boolean dumpInputToFile;

  private DumpOptions(
      Backend backend,
      Tool tool,
      CompilationMode compilationMode,
      int minAPI,
      DesugaredLibrarySpecification desugaredLibrarySpecification,
      boolean optimizeMultidexForLinearAlloc,
      int threadCount,
      DesugarState desugarState,
      Optional<Boolean> intermediate,
      Optional<Boolean> includeDataResources,
      Optional<Boolean> treeShaking,
      Optional<Boolean> minification,
      Optional<Boolean> forceProguardCompatibility,
      FeatureSplitConfiguration featureSplitConfiguration,
      ProguardConfiguration proguardConfiguration,
      List<ProguardConfigurationRule> mainDexKeepRules,
      Collection<StartupProfileProvider> startupProfileProviders,
      boolean enableMissingLibraryApiModeling,
      boolean isAndroidPlatformBuild,
      Map<String, String> systemProperties,
      boolean dumpInputToFile,
      String traceReferencesConsumer) {
    this.backend = backend;
    this.tool = tool;
    this.compilationMode = compilationMode;
    this.minApi = minAPI;
    this.desugaredLibrarySpecification = desugaredLibrarySpecification;
    this.optimizeMultidexForLinearAlloc = optimizeMultidexForLinearAlloc;
    this.threadCount = threadCount;
    this.desugarState = desugarState;
    this.intermediate = intermediate;
    this.includeDataResources = includeDataResources;
    this.treeShaking = treeShaking;
    this.minification = minification;
    this.forceProguardCompatibility = forceProguardCompatibility;
    this.featureSplitConfiguration = featureSplitConfiguration;
    this.proguardConfiguration = proguardConfiguration;
    this.mainDexKeepRules = mainDexKeepRules;
    this.startupProfileProviders = startupProfileProviders;
    this.enableMissingLibraryApiModeling = enableMissingLibraryApiModeling;
    this.isAndroidPlatformBuild = isAndroidPlatformBuild;
    this.systemProperties = systemProperties;
    this.dumpInputToFile = dumpInputToFile;
    this.traceReferencesConsumer = traceReferencesConsumer;
  }

  public String getBuildPropertiesFileContent() {
    StringBuilder builder = new StringBuilder();
    getBuildProperties()
        .forEach((key, value) -> builder.append(key).append("=").append(value).append("\n"));
    return builder.toString();
  }

  public Map<String, String> getBuildProperties() {
    Map<String, String> buildProperties = new LinkedHashMap<>();
    addDumpEntry(buildProperties, TOOL_KEY, tool.name());
    if (threadCount != ThreadUtils.NOT_SPECIFIED) {
      addDumpEntry(buildProperties, THREAD_COUNT_KEY, threadCount);
    }
    if (tool != Tool.TraceReferences) {
      // We keep the following values for backward compatibility.
      addDumpEntry(buildProperties, BACKEND_KEY, backend.name());
      addDumpEntry(
          buildProperties,
          MODE_KEY,
          compilationMode == CompilationMode.DEBUG ? DEBUG_MODE_VALUE : RELEASE_MODE_VALUE);
      addDumpEntry(buildProperties, MIN_API_KEY, minApi);
      addDumpEntry(
          buildProperties, OPTIMIZE_MULTIDEX_FOR_LINEAR_ALLOC_KEY, optimizeMultidexForLinearAlloc);
      addDumpEntry(buildProperties, DESUGAR_STATE_KEY, desugarState);
      addDumpEntry(
          buildProperties, ENABLE_MISSING_LIBRARY_API_MODELING, enableMissingLibraryApiModeling);
      if (isAndroidPlatformBuild) {
        addDumpEntry(buildProperties, ANDROID_PLATFORM_BUILD, isAndroidPlatformBuild);
      }
      addOptionalDumpEntry(buildProperties, INTERMEDIATE_KEY, intermediate);
      addOptionalDumpEntry(buildProperties, INCLUDE_DATA_RESOURCES_KEY, includeDataResources);
      addOptionalDumpEntry(buildProperties, TREE_SHAKING_KEY, treeShaking);
      addOptionalDumpEntry(
          buildProperties, FORCE_PROGUARD_COMPATIBILITY_KEY, forceProguardCompatibility);
    } else {
      addDumpEntry(buildProperties, TRACE_REFERENCES_CONSUMER, traceReferencesConsumer);
    }
    addOptionalDumpEntry(buildProperties, MINIFICATION_KEY, minification);
    ArrayList<String> sortedKeys = new ArrayList<>(systemProperties.keySet());
    sortedKeys.sort(String::compareTo);
    sortedKeys.forEach(
        key ->
            addDumpEntry(buildProperties, SYSTEM_PROPERTY_PREFIX + key, systemProperties.get(key)));
    return buildProperties;
  }

  public static void parse(String content, DumpOptions.Builder builder) {
    String[] lines = content.split("\n");
    for (String line : lines) {
      String trimmed = line.trim();
      int i = trimmed.indexOf('=');
      if (i < 0) {
        throw new RuntimeException("Invalid dump line. Expected = in line: '" + trimmed + "'");
      }
      String key = trimmed.substring(0, i).trim();
      String value = trimmed.substring(i + 1).trim();
      parseKeyValue(builder, key, value);
    }
  }

  private static void parseKeyValue(Builder builder, String key, String value) {
    switch (key) {
      case BACKEND_KEY:
        builder.setBackend(Backend.valueOf(value));
        return;
      case TOOL_KEY:
        builder.setTool(Tool.valueOf(value));
        return;
      case MODE_KEY:
        if (value.equals(DEBUG_MODE_VALUE)) {
          builder.setCompilationMode(CompilationMode.DEBUG);
        } else if (value.equals(RELEASE_MODE_VALUE)) {
          builder.setCompilationMode(CompilationMode.RELEASE);
        } else {
          parseKeyValueError(key, value);
        }
        return;
      case MIN_API_KEY:
        builder.setMinApi(Integer.parseInt(value));
        return;
      case OPTIMIZE_MULTIDEX_FOR_LINEAR_ALLOC_KEY:
        builder.setOptimizeMultidexForLinearAlloc(Boolean.parseBoolean(value));
        return;
      case THREAD_COUNT_KEY:
        builder.setThreadCount(Integer.parseInt(value));
        return;
      case DESUGAR_STATE_KEY:
        builder.setDesugarState(DesugarState.valueOf(value));
        return;
      case INTERMEDIATE_KEY:
        builder.setIntermediate(Boolean.parseBoolean(value));
        return;
      case INCLUDE_DATA_RESOURCES_KEY:
        builder.setIncludeDataResources(Optional.of(Boolean.parseBoolean(value)));
        return;
      case TREE_SHAKING_KEY:
        builder.setTreeShaking(Boolean.parseBoolean(value));
        return;
      case MINIFICATION_KEY:
        builder.setMinification(Boolean.parseBoolean(value));
        return;
      case FORCE_PROGUARD_COMPATIBILITY_KEY:
        builder.setForceProguardCompatibility(Boolean.parseBoolean(value));
        return;
      case TRACE_REFERENCES_CONSUMER:
        builder.setTraceReferencesConsumer(value);
        return;
      default:
        if (key.startsWith(SYSTEM_PROPERTY_PREFIX)) {
          builder.setSystemProperty(key.substring(SYSTEM_PROPERTY_PREFIX.length()), value);
        } else {
          parseKeyValueError(key, value);
        }
    }
  }

  private static void parseKeyValueError(String key, String value) {
    throw new RuntimeException("Unknown key value pair: " + key + " = " + value);
  }

  public Tool getTool() {
    return tool;
  }

  public CompilationMode getCompilationMode() {
    return compilationMode;
  }

  public int getMinApi() {
    return minApi;
  }

  private void addOptionalDumpEntry(
      Map<String, String> buildProperties, String key, Optional<?> optionalValue) {
    optionalValue.ifPresent(bool -> addDumpEntry(buildProperties, key, bool));
  }

  private void addDumpEntry(Map<String, String> buildProperties, String key, Object value) {
    buildProperties.put(key, Objects.toString(value));
  }

  private boolean hasDesugaredLibraryConfiguration() {
    return desugaredLibrarySpecification != null && !desugaredLibrarySpecification.isEmpty();
  }

  public String getDesugaredLibraryJsonSource() {
    if (hasDesugaredLibraryConfiguration()) {
      return desugaredLibrarySpecification.getJsonSource();
    }
    return null;
  }

  public FeatureSplitConfiguration getFeatureSplitConfiguration() {
    return featureSplitConfiguration;
  }

  public String getParsedProguardConfiguration() {
    return proguardConfiguration == null ? null : proguardConfiguration.getParsedConfiguration();
  }

  public boolean hasMainDexKeepRules() {
    return mainDexKeepRules != null && !mainDexKeepRules.isEmpty();
  }

  public List<ProguardConfigurationRule> getMainDexKeepRules() {
    return mainDexKeepRules;
  }

  public boolean hasStartupProfileProviders() {
    return startupProfileProviders != null && !startupProfileProviders.isEmpty();
  }

  public Collection<StartupProfileProvider> getStartupProfileProviders() {
    return startupProfileProviders;
  }

  public boolean dumpInputToFile() {
    return dumpInputToFile;
  }

  public static Builder builder(Tool tool) {
    return new Builder().setTool(tool);
  }

  public static class Builder {
    // Initialize backend to DEX for backwards compatibility.
    private Backend backend = Backend.DEX;
    private Tool tool;
    private CompilationMode compilationMode;
    private int minApi;
    private boolean optimizeMultidexForLinearAlloc;
    private int threadCount;
    private DesugarState desugarState;
    private Optional<Boolean> intermediate = Optional.empty();
    private Optional<Boolean> includeDataResources = Optional.empty();
    private Optional<Boolean> treeShaking = Optional.empty();
    private Optional<Boolean> minification = Optional.empty();
    private Optional<Boolean> forceProguardCompatibility = Optional.empty();
    // Dump if present.
    private DesugaredLibrarySpecification desugaredLibrarySpecification;
    private FeatureSplitConfiguration featureSplitConfiguration;
    private ProguardConfiguration proguardConfiguration;
    private List<ProguardConfigurationRule> mainDexKeepRules;
    private Collection<StartupProfileProvider> startupProfileProviders;

    private boolean enableMissingLibraryApiModeling = false;
    private boolean isAndroidPlatformBuild = false;

    private String traceReferencesConsumer = null;

    private Map<String, String> systemProperties = new HashMap<>();

    // Reporting only.
    private boolean dumpInputToFile;

    public Builder() {}

    public Builder setBackend(Backend backend) {
      this.backend = backend;
      return this;
    }

    public Builder setTool(Tool tool) {
      this.tool = tool;
      return this;
    }

    public Builder setTraceReferencesConsumer(String traceReferencesConsumer) {
      this.traceReferencesConsumer = traceReferencesConsumer;
      return this;
    }

    public Builder setCompilationMode(CompilationMode compilationMode) {
      this.compilationMode = compilationMode;
      return this;
    }

    public Builder setMinApi(int minAPI) {
      this.minApi = minAPI;
      return this;
    }

    public Builder setDesugaredLibraryConfiguration(
        DesugaredLibrarySpecification desugaredLibrarySpecification) {
      this.desugaredLibrarySpecification = desugaredLibrarySpecification;
      return this;
    }

    public Builder setOptimizeMultidexForLinearAlloc(boolean optimizeMultidexForLinearAlloc) {
      this.optimizeMultidexForLinearAlloc = optimizeMultidexForLinearAlloc;
      return this;
    }

    public Builder setThreadCount(int threadCount) {
      this.threadCount = threadCount;
      return this;
    }

    public Builder setDesugarState(DesugarState desugarState) {
      this.desugarState = desugarState;
      return this;
    }

    public Builder setIntermediate(boolean intermediate) {
      this.intermediate = Optional.of(intermediate);
      return this;
    }

    public Builder setIncludeDataResources(Optional<Boolean> includeDataResources) {
      this.includeDataResources = includeDataResources;
      return this;
    }

    public Builder setForceProguardCompatibility(boolean forceProguardCompatibility) {
      this.forceProguardCompatibility = Optional.of(forceProguardCompatibility);
      return this;
    }

    public Builder setMinification(boolean minification) {
      this.minification = Optional.of(minification);
      return this;
    }

    public Builder setTreeShaking(boolean treeShaking) {
      this.treeShaking = Optional.of(treeShaking);
      return this;
    }

    public Builder setDumpInputToFile(boolean dumpInputToFile) {
      this.dumpInputToFile = dumpInputToFile;
      return this;
    }

    public Builder setFeatureSplitConfiguration(
        FeatureSplitConfiguration featureSplitConfiguration) {
      this.featureSplitConfiguration = featureSplitConfiguration;
      return this;
    }

    public Builder setProguardConfiguration(ProguardConfiguration proguardConfiguration) {
      this.proguardConfiguration = proguardConfiguration;
      return this;
    }

    public Builder setMainDexKeepRules(List<ProguardConfigurationRule> mainDexKeepRules) {
      this.mainDexKeepRules = mainDexKeepRules;
      return this;
    }

    public Builder setStartupProfileProviders(
        Collection<StartupProfileProvider> startupProfileProviders) {
      this.startupProfileProviders = startupProfileProviders;
      return this;
    }

    public Builder setEnableMissingLibraryApiModeling(boolean value) {
      enableMissingLibraryApiModeling = value;
      return this;
    }

    public Builder setAndroidPlatformBuild(boolean value) {
      isAndroidPlatformBuild = value;
      return this;
    }

    public Builder setSystemProperty(String key, String value) {
      this.systemProperties.put(key, value);
      return this;
    }

    public Builder readCurrentSystemProperties() {
      getCurrentSystemProperties().forEach(this::setSystemProperty);
      return this;
    }

    public static Map<String, String> getCurrentSystemProperties() {
      Map<String, String> systemProperties = new TreeMap<>();
      System.getProperties()
          .stringPropertyNames()
          .forEach(
              name -> {
                if (name.startsWith("com.android.tools.r8.")) {
                  String value = System.getProperty(name);
                  systemProperties.put(name, value);
                }
              });
      return systemProperties;
    }

    public DumpOptions build() {
      assert tool != null;
      assert tool == Tool.TraceReferences || backend != null;
      return new DumpOptions(
          backend,
          tool,
          compilationMode,
          minApi,
          desugaredLibrarySpecification,
          optimizeMultidexForLinearAlloc,
          threadCount,
          desugarState,
          intermediate,
          includeDataResources,
          treeShaking,
          minification,
          forceProguardCompatibility,
          featureSplitConfiguration,
          proguardConfiguration,
          mainDexKeepRules,
          startupProfileProviders,
          enableMissingLibraryApiModeling,
          isAndroidPlatformBuild,
          systemProperties,
          dumpInputToFile,
          traceReferencesConsumer);
    }
  }
}
