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

import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;

import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.ApplicationWriter;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

public class DexFileMergerHelper {

  private final Map<String, Integer> inputOrdering;

  private DexFileMergerHelper(Map<String, Integer> inputOrdering) {
    this.inputOrdering = inputOrdering;
  }

  private DexProgramClass keepFirstProgramClassConflictResolver(
      DexProgramClass a, DexProgramClass b) {
    String aPath = a.getOrigin().parent().part();
    String bPath = b.getOrigin().parent().part();
    Integer aIndex = inputOrdering.get(aPath);
    Integer bIndex = inputOrdering.get(bPath);
    if (aIndex == null || bIndex == null) {
      StringBuilder builder = new StringBuilder();
      builder.append("Class parent paths not found among input paths: ");
      if (aIndex == null) {
        builder.append(aPath);
      }
      if (bIndex == null) {
        if (aIndex == null) {
          builder.append(", ");
        }
        builder.append(bPath);
      }
      throw new RuntimeException(builder.toString());
    }
    return aIndex <= bIndex ? a.get() : b.get();
  }

  public static void run(
      D8Command command, Boolean minimalMainDex, Map<String, Integer> inputOrdering)
      throws CompilationFailedException {
    InternalOptions options = command.getInternalOptions();
    ExceptionUtils.withD8CompilationHandler(
        options.reporter,
        () -> runInternal(command.getInputApp(), options, minimalMainDex, inputOrdering));
  }

  private static void runInternal(
      AndroidApp inputApp,
      InternalOptions options,
      Boolean minimalMainDex,
      Map<String, Integer> inputOrdering)
      throws IOException {
    options.desugarState = DesugarState.OFF;
    options.enableMainDexListCheck = false;
    options.minimalMainDex = minimalMainDex;
    assert !options.isMinifying();
    options.enableInlining = false;
    options.outline.enabled = false;

    ExecutorService executor = ThreadUtils.getExecutorService(ThreadUtils.NOT_SPECIFIED);
    try {
      try {
        Timing timing = new Timing("DexFileMerger");
        ApplicationReader applicationReader = new ApplicationReader(inputApp, options, timing);
        DexApplication app =
            applicationReader.read(
                null,
                executor,
                new DexFileMergerHelper(inputOrdering)::keepFirstProgramClassConflictResolver);

        AppView<AppInfo> appView =
            AppView.createForD8(
                AppInfo.createInitialAppInfo(app, applicationReader.readMainDexClasses(app)));

        D8.optimize(appView, options, timing, executor);

        List<Marker> markers = appView.dexItemFactory().extractMarkers();

        assert !options.hasMethodsFilter();
        ApplicationWriter writer =
            new ApplicationWriter(
                appView,
                markers,
                GraphLens.getIdentityLens(),
                InitClassLens.getDefault(),
                NamingLens.getIdentityLens(),
                null);
        writer.write(executor);
        options.printWarnings();
      } catch (ExecutionException e) {
        throw unwrapExecutionException(e);
      } finally {
        options.signalFinishedToConsumers();
      }
    } finally {
      executor.shutdown();
    }
  }

  public static void runD8ForTesting(D8Command command, boolean dontCreateMarkerInD8)
      throws CompilationFailedException {
    InternalOptions options = command.getInternalOptions();
    options.testing.dontCreateMarkerInD8 = dontCreateMarkerInD8;
    D8.runForTesting(command.getInputApp(), options);
  }
}
