package com.android.tools.r8;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.AtlasApplicationWriter;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.MainDexError;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

/**
 * AtlasD8
 *
 * @author zhayu.ll
 * @date 18/4/3
 */
public class AtlasD8 {
    private static final String VERSION = "v0.1.14";
    private static final int STATUS_ERROR = 1;

    private AtlasD8() {
    }

    public static D8Output run(D8Command command) throws IOException {
        InternalOptions options = command.getInternalOptions();
        options.skipDebugLineNumberOpt = true;
        CompilationResult result = runForTesting(command.getInputApp(), options);

        assert result != null;

        D8Output output = new D8Output(result.androidApp, command.getOutputMode());
        if (command.getOutputPath() != null) {
            output.write(command.getOutputPath());
        }

        return output;
    }

    public static D8Output run(D8Command command, ExecutorService executor) throws IOException {
        InternalOptions options = command.getInternalOptions();
        options.skipDebugLineNumberOpt = true;
        CompilationResult result = runForTesting(command.getInputApp(), options, executor);

        assert result != null;

        D8Output output = new D8Output(result.androidApp, command.getOutputMode());
        if (command.getOutputPath() != null) {
            output.write(command.getOutputPath());
        }

        return output;
    }

    private static void run(String[] args) throws IOException, CompilationException {
        D8Command.Builder builder = D8Command.parse(args);
        if (builder.getOutputPath() == null) {
            builder.setOutputPath(Paths.get("."));
        }

        D8Command command = builder.build();
        if (command.isPrintHelp()) {
            System.out.println(D8Command.USAGE_MESSAGE);
        } else if (command.isPrintVersion()) {
            System.out.println("D8 v0.1.14");
        } else {
            run(command);
        }
    }

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            System.err.println(D8Command.USAGE_MESSAGE);
            System.exit(1);
        }

        try {
            run(args);
        } catch (NoSuchFileException var3) {
            System.err.println("File not found: " + var3.getFile());
            System.exit(1);
        } catch (FileAlreadyExistsException var4) {
            System.err.println("File already exists: " + var4.getFile());
            System.exit(1);
        } catch (IOException var5) {
            System.err.println("Failed to read or write application files: " + var5.getMessage());
            System.exit(1);
        } catch (RuntimeException var6) {
            System.err.println("Compilation failed with an internal error.");
            Throwable cause = var6.getCause() == null ? var6 : var6.getCause();
            ((Throwable)cause).printStackTrace();
            System.exit(1);
        } catch (CompilationException var7) {
            System.err.println("Compilation failed: " + var7.getMessage());
            System.err.println(D8Command.USAGE_MESSAGE);
            System.exit(1);
        }

    }

    static CompilationResult runForTesting(AndroidApp inputApp, InternalOptions options) throws IOException {
        ExecutorService executor = ThreadUtils.getExecutorService(options);

        CompilationResult var3;
        try {
            var3 = runForTesting(inputApp, options, executor);
        } finally {
            executor.shutdown();
        }

        return var3;
    }

    private static Marker getMarker(InternalOptions options) {
        return options.hasMarker() ? options.getMarker() : (new Marker(Marker.Tool.D8)).put("version", "v0.1.14").put("min-api", options.minApiLevel);
    }

    private static CompilationResult runForTesting(AndroidApp inputApp, InternalOptions options, ExecutorService executor) throws IOException {
        try {
            assert !inputApp.hasPackageDistribution();

            options.skipMinification = true;
            options.inlineAccessors = false;
            options.outline.enabled = false;
            Timing timing = new Timing("DX timer");
            DexApplication app = (new ApplicationReader(inputApp, options, timing)).read(executor);
            AppInfo appInfo = new AppInfo(app);
            app = optimize(app, appInfo, options, timing, executor);
            if (options.hasMethodsFilter()) {
                System.out.println("Finished compilation with method filter: ");
                options.methodsFilter.forEach((m) -> {
                    System.out.println("  - " + m);
                });
                return null;
            } else {
                Marker marker = getMarker(options);
                CompilationResult output = new CompilationResult((new AtlasApplicationWriter(app, appInfo, options, marker, (byte[])null, NamingLens.getIdentityLens(), (byte[])null)).write((PackageDistribution)null, executor), app, appInfo);
                options.printWarnings();
                return output;
            }
        } catch (MainDexError var8) {
            throw new CompilationError(var8.getMessageForD8());
        } catch (ExecutionException var9) {
            if (var9.getCause() instanceof CompilationError) {
                throw (CompilationError)var9.getCause();
            } else {
                throw new RuntimeException(var9.getMessage(), var9.getCause());
            }
        }
    }

    private static DexApplication optimize(DexApplication application, AppInfo appInfo, InternalOptions options, Timing timing, ExecutorService executor) throws IOException, ExecutionException {
        CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
        IRConverter converter = new IRConverter(timing, application, appInfo, options, printer);
        application = converter.convertToDex(executor);
        if (options.printCfg) {
            if (options.printCfgFile != null && !options.printCfgFile.isEmpty()) {
                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(options.printCfgFile), StandardCharsets.UTF_8);
                Throwable var8 = null;

                try {
                    writer.write(printer.toString());
                } catch (Throwable var17) {
                    var8 = var17;
                    throw var17;
                } finally {
                    if (writer != null) {
                        if (var8 != null) {
                            try {
                                writer.close();
                            } catch (Throwable var16) {
                                var8.addSuppressed(var16);
                            }
                        } else {
                            writer.close();
                        }
                    }

                }
            } else {
                System.out.print(printer.toString());
            }
        }

        return application;
    }
}

@@ -1243,32 +1243,108 @@
 mberOpt = true;%0A
+        options.skipDebugInfoOpt = true;%0A        options.printTimes = true;%0A
         Compilat
@@ -1865,32 +1865,108 @@
 mberOpt = true;%0A
+        options.skipDebugInfoOpt = true;%0A        options.printTimes = true;%0A
         Compilat

add debug info