/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package vogar.android;

import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;

import vogar.Classpath;
import vogar.Dexer;
import vogar.HostFileCache;
import vogar.Language;
import vogar.Log;
import vogar.Md5Cache;
import vogar.ModeId;
import vogar.commands.Command;
import vogar.commands.Mkdir;
import vogar.util.Strings;



/**
 * Android SDK commands such as adb, aapt and dx.
 */
public class AndroidSdk {

    private static final String D8_COMMAND_NAME = "d8";
    private static final String DX_COMMAND_NAME = "dx";
    private static final String ARBITRARY_BUILD_TOOL_NAME = D8_COMMAND_NAME;

    private final Log log;
    private final Mkdir mkdir;
    private final File[] compilationClasspath;
    private final String androidJarPath;
    private final String desugarJarPath;
    private final Md5Cache dexCache;
    private final Language language;

    public static Collection<File> defaultExpectations() {
        return Collections.singletonList(new File("libcore/expectations/knownfailures.txt"));
    }

    /**
     * Create an {@link AndroidSdk}.
     *
     * <p>Searches the PATH used to run this and scans the file system in order to determine the
     * compilation class path and android jar path.
     */
    public static AndroidSdk createAndroidSdk(
            Log log, Mkdir mkdir, ModeId modeId, Language language) {
        List<String> path = new Command.Builder(log).args("which", ARBITRARY_BUILD_TOOL_NAME)
                .permitNonZeroExitStatus(true)
                .execute();
        if (path.isEmpty()) {
            throw new RuntimeException(ARBITRARY_BUILD_TOOL_NAME + " not found");
        }
        File buildTool = new File(path.get(0)).getAbsoluteFile();
        String buildToolDirString = getParentFileNOrLast(buildTool, 1).getName();

        List<String> adbPath = new Command.Builder(log)
                .args("which", "adb")
                .permitNonZeroExitStatus(true)
                .execute();

        File adb;
        if (!adbPath.isEmpty()) {
            adb = new File(adbPath.get(0));
        } else {
            adb = null;  // Could not find adb.
        }

        /*
         * Determine if we are running with a provided SDK or in the AOSP source tree.
         *
         * Android build tree (target):
         *  ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/aapt
         *  ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/adb
         *  ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/dx
         *  ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/desugar.jar
         *  ${ANDROID_BUILD_TOP}/out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates
         *      /classes.jar
         */

        File[] compilationClasspath;
        String androidJarPath;
        String desugarJarPath = null;

        // Accept that we are running in an SDK if the user has added the build-tools or
        // platform-tools to their path.
        boolean buildToolsPathValid = "build-tools".equals(getParentFileNOrLast(buildTool, 2)
                .getName());
        boolean isAdbPathValid = (adb != null) &&
                "platform-tools".equals(getParentFileNOrLast(adb, 1).getName());
        if (buildToolsPathValid || isAdbPathValid) {
            File sdkRoot = buildToolsPathValid
                    ? getParentFileNOrLast(buildTool, 3)  // if build tool path invalid then
                    : getParentFileNOrLast(adb, 2);  // adb must be valid.
            File newestPlatform = getNewestPlatform(sdkRoot);
            log.verbose("Using android platform: " + newestPlatform);
            compilationClasspath = new File[] { new File(newestPlatform, "android.jar") };
            androidJarPath = new File(newestPlatform.getAbsolutePath(), "android.jar")
                    .getAbsolutePath();
            log.verbose("using android sdk: " + sdkRoot);

            // There must be a desugar.jar in the build tool directory.
            desugarJarPath = buildToolDirString + "/desugar.jar";
            File desugarJarFile = new File(desugarJarPath);
            if (!desugarJarFile.exists()) {
                throw new RuntimeException("Could not find " + desugarJarPath);
            }
        } else if ("bin".equals(buildToolDirString)) {
            log.verbose("Using android source build mode to find dependencies.");
            String tmpJarPath = "prebuilts/sdk/current/public/android.jar";
            String androidBuildTop = System.getenv("ANDROID_BUILD_TOP");
            if (!com.google.common.base.Strings.isNullOrEmpty(androidBuildTop)) {
                tmpJarPath = androidBuildTop + "/prebuilts/sdk/current/public/android.jar";
            } else {
                log.warn("Assuming current directory is android build tree root.");
            }
            androidJarPath = tmpJarPath;

            String outDir = System.getenv("OUT_DIR");
            if (Strings.isNullOrEmpty(outDir)) {
                if (Strings.isNullOrEmpty(androidBuildTop)) {
                    outDir = ".";
                    log.warn("Assuming we are in android build tree root to find libraries.");
                } else {
                    log.verbose("Using ANDROID_BUILD_TOP to find built libraries.");
                    outDir = androidBuildTop;
                }
                outDir += "/out/";
            } else {
                log.verbose("Using OUT_DIR environment variable for finding built libs.");
                outDir += "/";
            }

            String hostOutDir = System.getenv("ANDROID_HOST_OUT");
            if (!Strings.isNullOrEmpty(hostOutDir)) {
                log.verbose("Using ANDROID_HOST_OUT to find host libraries.");
            } else {
                // Handle the case where lunch hasn't been run. Guess the architecture.
                log.warn("ANDROID_HOST_OUT not set. Assuming linux-x86");
                hostOutDir = outDir + "/host/linux-x86";
            }

            String desugarPattern = hostOutDir + "/framework/desugar.jar";
            File desugarJar = new File(desugarPattern);

            if (!desugarJar.exists()) {
                throw new RuntimeException("Could not find " + desugarPattern);
            }

            desugarJarPath = desugarJar.getPath();

            String pattern = outDir + "target/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
            if (modeId.isHost()) {
                pattern = outDir + "host/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
            }
            pattern += ".jar";

            String[] jarNames = modeId.getJarNames();
            compilationClasspath = new File[jarNames.length];
            for (int i = 0; i < jarNames.length; i++) {
                String jar = jarNames[i];
                compilationClasspath[i] = new File(String.format(pattern, jar));
            }
        } else {
            throw new RuntimeException("Couldn't derive Android home from "
                    + ARBITRARY_BUILD_TOOL_NAME);
        }

        return new AndroidSdk(log, mkdir, compilationClasspath, androidJarPath, desugarJarPath,
                new HostFileCache(log, mkdir), language);
    }

    @VisibleForTesting
    AndroidSdk(Log log, Mkdir mkdir, File[] compilationClasspath, String androidJarPath,
               String desugarJarPath, HostFileCache hostFileCache, Language language) {
        this.log = log;
        this.mkdir = mkdir;
        this.compilationClasspath = compilationClasspath;
        this.androidJarPath = androidJarPath;
        this.desugarJarPath = desugarJarPath;
        this.dexCache = new Md5Cache(log, "dex", hostFileCache);
        this.language = language;
    }

    // Goes up N levels in the filesystem hierarchy. Return the last file that exists if this goes
    // past /.
    private static File getParentFileNOrLast(File f, int n) {
        File lastKnownExists = f;
        for (int i = 0; i < n; i++) {
            File parentFile = lastKnownExists.getParentFile();
            if (parentFile == null) {
                return lastKnownExists;
            }
            lastKnownExists = parentFile;
        }
        return lastKnownExists;
    }

    /**
     * Returns the platform directory that has the highest API version. API
     * platform directories are named like "android-9" or "android-11".
     */
    private static File getNewestPlatform(File sdkRoot) {
        File newestPlatform = null;
        int newestPlatformVersion = 0;
        File[] platforms = new File(sdkRoot, "platforms").listFiles();
        if (platforms != null) {
            for (File platform : platforms) {
                try {
                    int version =
                            Integer.parseInt(platform.getName().substring("android-".length()));
                    if (version > newestPlatformVersion) {
                        newestPlatform = platform;
                        newestPlatformVersion = version;
                    }
                } catch (NumberFormatException ignore) {
                    // Ignore non-numeric preview versions like android-Honeycomb
                }
            }
        }
        if (newestPlatform == null) {
            throw new IllegalStateException("Cannot find newest platform in " + sdkRoot);
        }
        return newestPlatform;
    }

    public static Collection<File> defaultSourcePath() {
        return filterNonExistentPathsFrom("libcore/support/src/test/java",
                                          "external/mockwebserver/src/main/java/");
    }

    private static Collection<File> filterNonExistentPathsFrom(String... paths) {
        ArrayList<File> result = new ArrayList<File>();
        String buildRoot = System.getenv("ANDROID_BUILD_TOP");
        for (String path : paths) {
            File file = new File(buildRoot, path);
            if (file.exists()) {
                result.add(file);
            }
        }
        return result;
    }

    public File[] getCompilationClasspath() {
        return compilationClasspath;
    }

    /**
     * Converts all the .class files on 'classpath' into a dex file written to 'output'.
     *
     * @param multidex could the output be more than 1 dex file?
     * @param output the File for the classes.dex that will be generated as a result of this call.
     * @param outputTempDir a temporary directory which can store intermediate files generated.
     * @param classpath a list of files/directories containing .class files that are
     *                  merged together and converted into the output (dex) file.
     * @param dependentCp classes that are referenced in classpath but are not themselves on the
     *                    classpath must be listed in dependentCp, this is required to be able
     *                    resolve all class dependencies. The classes in dependentCp are <i>not</i>
     *                    included in the output dex file.
     * @param dexer Which dex tool to use
     */
    public void dex(boolean multidex, File output, File outputTempDir,
            Classpath classpath, Classpath dependentCp, Dexer dexer) {
        mkdir.mkdirs(output.getParentFile());

        String classpathSubKey = dexCache.makeKey(classpath);
        String cacheKey = null;
        if (classpathSubKey != null) {
            String multidexSubKey = "mdex=" + multidex;
            cacheKey = dexCache.makeKey(classpathSubKey, multidexSubKey);
            boolean cacheHit = dexCache.getFromCache(output, cacheKey);
            if (cacheHit) {
                log.verbose("dex cache hit for " + classpath);
                return;
            }
        }

        // Call desugar first to remove invoke-dynamic LambdaMetaFactory usage,
        // which ART doesn't support.
        List<String> desugarOutputFilePaths = desugar(outputTempDir, classpath, dependentCp);

        /*
         * We pass --core-library so that we can write tests in the
         * same package they're testing, even when that's a core
         * library package. If you're actually just using this tool to
         * execute arbitrary code, this has the unfortunate
         * side-effect of preventing "dx" from protecting you from
         * yourself.
         *
         * Memory options pulled from build/core/definitions.mk to
         * handle large dx input when building dex for APK.
         */

        Command.Builder builder = new Command.Builder(log);
        switch (dexer) {
            case DX:
                builder.args(DX_COMMAND_NAME);
                builder.args("-JXms16M").args("-JXmx1536M");
                builder.args("--min-sdk-version=" + language.getMinApiLevel());
                if (multidex) {
                    builder.args("--multi-dex");
                }
                builder.args("--dex")
                    .args("--output=" + output)
                    .args("--core-library")
                    .args(desugarOutputFilePaths);
                builder.execute();
                break;
            case D8:
                List<String> sanitizedDesugarOutputFilePaths;
                try {
                    sanitizedDesugarOutputFilePaths = removeDexFilesForD8(desugarOutputFilePaths);
                } catch (IOException e) {
                    throw new RuntimeException("Error while removing dex files from archive", e);
                }
                builder.args(D8_COMMAND_NAME);
                builder.args("-JXms16M").args("-JXmx1536M");
                builder
                    .args("--min-api").args(language.getMinApiLevel())
                    .args("--output").args(output)
                    .args(sanitizedDesugarOutputFilePaths);
                builder.execute();
                if (output.toString().endsWith(".jar")) {
                    try {
                        fixD8JarOutput(output, desugarOutputFilePaths);
                    } catch (IOException e) {
                        throw new RuntimeException("Error while fixing d8 output", e);
                    }
                }
                break;
            default:
                throw new RuntimeException("Unsupported dexer: " + dexer);

        }

        dexCache.insert(cacheKey, output);
    }

    /**
     * Produces an output file like dx does. dx generates jar files containing all resources present
     * in the input files.
     * d8 only produces a jar file containing dex and none of the input resources, and
     * will produce no file at all if there are no .class files to process.
     */
    private static void fixD8JarOutput(File output, List<String> inputs) throws IOException {
        List<String> filesToMerge = new ArrayList<>(inputs);

        // JarOutputStream is not keen on appending entries to existing file so we move the output
        // files if it already exists.
        File outputCopy = null;
        if (output.exists()) {
            outputCopy = new File(output.toString() + ".copy");
            output.renameTo(outputCopy);
            filesToMerge.add(outputCopy.toString());
        }

        byte[] buffer = new byte[4096];
        try (JarOutputStream outputJar = new JarOutputStream(new FileOutputStream(output))) {
            for (String fileToMerge : filesToMerge) {
                copyJarContentExcludingClassFiles(buffer, fileToMerge, outputJar);
            }
        } finally {
            if (outputCopy != null) {
                outputCopy.delete();
            }
        }
    }

    /**
      * Removes DEX files from an archive and preserve the rest.
      */
    private List<String> removeDexFilesForD8(List<String> fileNames) throws IOException {
        byte[] buffer = new byte[4096];
        List<String> processedFiles = new ArrayList<>(fileNames.size());
        for (String inputFileName : fileNames) {
            String jarExtension = ".jar";
            String outputFileName;
            if (inputFileName.endsWith(jarExtension)) {
                outputFileName =
                    inputFileName.substring(0, inputFileName.length() - jarExtension.length())
                    + "-d8" + jarExtension;
            } else {
              outputFileName = inputFileName + "-d8" + jarExtension;
            }
            try (JarOutputStream outputJar =
                    new JarOutputStream(new FileOutputStream(outputFileName))) {
                copyJarContentExcludingFiles(buffer, inputFileName, outputJar, ".dex");
            }
            processedFiles.add(outputFileName);
        }
        return processedFiles;
    }

    private static void copyJarContentExcludingClassFiles(byte[] buffer, String inputJarName,
            JarOutputStream outputJar) throws IOException {
        copyJarContentExcludingFiles(buffer, inputJarName, outputJar, ".class");
    }

    private static void copyJarContentExcludingFiles(byte[] buffer, String inputJarName,
            JarOutputStream outputJar, String extensionToExclude) throws IOException {

        try (JarInputStream inputJar = new JarInputStream(new FileInputStream(inputJarName))) {
            for (JarEntry entry = inputJar.getNextJarEntry();
                    entry != null;
                    entry = inputJar.getNextJarEntry()) {
                if (entry.getName().endsWith(extensionToExclude)) {
                    continue;
                }

                // Skip directories as they can cause duplicates.
                if (entry.isDirectory()) {
                    continue;
                }

                outputJar.putNextEntry(entry);

                int length;
                while ((length = inputJar.read(buffer)) >= 0) {
                    if (length > 0) {
                        outputJar.write(buffer, 0, length);
                    }
                }
                outputJar.closeEntry();
            }
        }
    }

    // Runs desugar on classpath as the input with dependentCp as the classpath_entry.
    // Returns the generated output list of files.
    private List<String> desugar(File outputTempDir, Classpath classpath, Classpath dependentCp) {
        Command.Builder builder = new Command.Builder(log)
                .args("java", "-jar", desugarJarPath);

        // Ensure that libcore is on the bootclasspath for desugar,
        // otherwise it tries to use the java command's bootclasspath.
        for (File f : compilationClasspath) {
            builder.args("--bootclasspath_entry", f.getPath());
        }

        // Desugar needs to actively resolve classes that the original inputs
        // were compiled against. Dx does not; so it doesn't use dependentCp.
        for (File f : dependentCp.getElements()) {
            builder.args("--classpath_entry", f.getPath());
        }

        builder.args("--core_library")
                .args("--min_sdk_version", language.getMinApiLevel());

        // Build the -i (input) and -o (output) arguments.
        // Every input from classpath corresponds to a new output temp file into
        // desugarTempDir.
        File desugarTempDir;
        {
            // Generate a temporary list of files that correspond to the 'classpath';
            // desugar will then convert the files in 'classpath' into 'desugarClasspath'.
            if (!outputTempDir.isDirectory()) {
                throw new AssertionError(
                        "outputTempDir must be a directory: " + outputTempDir.getPath());
            }

            String desugarTempDirPath = outputTempDir.getPath() + "/desugar";
            desugarTempDir = new File(desugarTempDirPath);
            desugarTempDir.mkdirs();
            if (!desugarTempDir.exists()) {
                throw new AssertionError(
                        "desugarTempDir; failed to create " + desugarTempDirPath);
            }
        }

        // Create unique file names to support non-unique classpath base names.
        //
        // For example:
        //
        // Classpath("/x/y.jar:/z/y.jar:/a/b.jar") ->
        // Output Files("${tmp}/0y.jar:${tmp}/1y.jar:${tmp}/2b.jar")
        int uniqueCounter = 0;
        List<String> desugarOutputFilePaths = new ArrayList<String>();

        for (File desugarInput : classpath.getElements()) {
            String tmpName = uniqueCounter + desugarInput.getName();
            ++uniqueCounter;

            String desugarOutputPath = desugarTempDir.getPath() + "/" + tmpName;
            desugarOutputFilePaths.add(desugarOutputPath);

            builder.args("-i", desugarInput.getPath())
                    .args("-o", desugarOutputPath);
        }

        builder.execute();

        return desugarOutputFilePaths;
    }

    public void packageApk(File apk, File manifest) {
        new Command(log, "aapt",
                "package",
                "-F", apk.getPath(),
                "-M", manifest.getPath(),
                "-I", androidJarPath,
                "--version-name", "1.0",
                "--version-code", "1").execute();
    }

    public void addToApk(File apk, File dex) {
        new Command(log, "aapt", "add", "-k", apk.getPath(), dex.getPath()).execute();
    }

    public void install(File apk) {
        new Command(log, "adb", "install", "-r", apk.getPath()).execute();
    }

    public void uninstall(String packageName) {
        new Command.Builder(log)
                .args("adb", "uninstall", packageName)
                .permitNonZeroExitStatus(true)
                .execute();
    }
}
