/*
 * 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 java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
import vogar.Classpath;
import vogar.HostFileCache;
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 {

    // $BOOTCLASSPATH defined by system/core/rootdir/init.rc
    public static final String[] BOOTCLASSPATH = new String[] { "core-libart",
                                                                "conscrypt",
                                                                "okhttp",
                                                                "core-junit",
                                                                "bouncycastle",
                                                                "ext",
                                                                "framework",
                                                                "telephony-common",
                                                                "mms-common",
                                                                "framework",
                                                                "android.policy",
                                                                "services",
                                                                "apache-xml"};


    public static final String[] HOST_BOOTCLASSPATH = new String[] {
            "core-libart-hostdex",
            "conscrypt-hostdex",
            "okhttp-hostdex",
            "bouncycastle-hostdex",
    };

    private final Log log;
    private final Mkdir mkdir;
    private final File[] compilationClasspath;
    public final DeviceFilesystem deviceFilesystem;
    private final boolean useJack;

    private Md5Cache dexCache;
    private Md5Cache pushCache;

    public static Collection<File> defaultExpectations() {
        File[] files = new File("libcore/expectations").listFiles(new FilenameFilter() {
            // ignore obviously temporary files
            public boolean accept(File dir, String name) {
                return !name.endsWith("~") && !name.startsWith(".");
            }
        });
        return (files != null) ? Arrays.asList(files) : Collections.<File>emptyList();
    }

    public AndroidSdk(Log log, Mkdir mkdir, ModeId modeId, boolean useJack) {
        this.log = log;
        this.mkdir = mkdir;
        this.deviceFilesystem = new DeviceFilesystem(log, "adb", "shell");
        this.useJack = useJack;

        List<String> path = new Command(log, "which", "adb").execute();
        if (path.isEmpty()) {
            throw new RuntimeException("adb not found");
        }
        File adb = new File(path.get(0)).getAbsoluteFile();
        String parentFileName = adb.getParentFile().getName();

        /*
         * We probably get aapt/adb/dx from either a copy of the Android SDK or a copy
         * of the Android source code. In either case, all three tools are in the same
         * directory as each other.
         *
         * Android SDK >= v9 (gingerbread):
         *  <sdk>/platform-tools/aapt
         *  <sdk>/platform-tools/adb
         *  <sdk>/platform-tools/dx
         *  <sdk>/platforms/android-?/android.jar
         *
         * Android build tree (target):
         *  <source>/out/host/linux-x86/bin/aapt
         *  <source>/out/host/linux-x86/bin/adb
         *  <source>/out/host/linux-x86/bin/dx
         *  <source>/out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar
         */

        if ("platform-tools".equals(parentFileName)) {
            File sdkRoot = adb.getParentFile().getParentFile();
            File newestPlatform = getNewestPlatform(sdkRoot);
            log.verbose("using android platform: " + newestPlatform);
            compilationClasspath = new File[] { new File(newestPlatform, "android.jar") };
            log.verbose("using android sdk: " + sdkRoot);
        } else if ("bin".equals(parentFileName)) {
            File sourceRoot = adb.getParentFile().getParentFile()
                    .getParentFile().getParentFile().getParentFile();
            log.verbose("using android build tree: " + sourceRoot);

            String pattern = "out/target/common/obj/JAVA_LIBRARIES/%s_intermediates/classes.jar";
            if (modeId.isHost()) {
                pattern = "out/host/common/obj/JAVA_LIBRARIES/%s_intermediates/classes"
                        + ((useJack) ? ".jack" : ".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(sourceRoot, String.format(pattern, jar));
            }
        } else {
            throw new RuntimeException("Couldn't derive Android home from " + adb);
        }
    }

    /**
     * Returns the platform directory that has the highest API version. API
     * platform directories are named like "android-9" or "android-11".
     */
    private File getNewestPlatform(File sdkRoot) {
        File newestPlatform = null;
        int newestPlatformVersion = 0;
        for (File platform : new File(sdkRoot, "platforms").listFiles()) {
            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
            }
        }
        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;
    }

    public void setCaches(HostFileCache hostFileCache, DeviceFileCache deviceCache) {
        this.dexCache = new Md5Cache(log, "dex", hostFileCache);
        this.pushCache = new Md5Cache(log, "pushed", deviceCache);
    }

    /**
     * Converts all the .class files on 'classpath' into a dex file written to 'output'.
     */
    public void dex(File output, Classpath classpath) {
        mkdir.mkdirs(output.getParentFile());

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

        /*
         * 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.
         */
        new Command.Builder(log)
                .args("dx")
                .args("-JXms16M")
                .args("-JXmx1536M")
                .args("--dex")
                .args("--output=" + output)
                .args("--core-library")
                .args((Object[]) Strings.objectsToStrings(classpath.getElements())).execute();
        dexCache.insert(key, output);
    }

    public void packageApk(File apk, File manifest) {
        List<String> aapt = new ArrayList<String>(Arrays.asList("aapt",
                                                                "package",
                                                                "-F", apk.getPath(),
                                                                "-M", manifest.getPath(),
                                                                "-I", "prebuilts/sdk/current/android.jar"));
        new Command(log, aapt).execute();
    }

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

    public void mv(File source, File destination) {
        new Command(log, "adb", "shell", "mv", source.getPath(), destination.getPath()).execute();
    }

    public void rm(File name) {
        new Command(log, "adb", "shell", "rm", "-r", name.getPath()).execute();
    }

    public void cp(File source, File destination) {
        // adb doesn't support "cp" command directly
        new Command(log, "adb", "shell", "cat", source.getPath(), ">", destination.getPath())
                .execute();
    }

    public void pull(File remote, File local) {
        new Command(log, "adb", "pull", remote.getPath(), local.getPath()).execute();
    }

    public void push(File local, File remote) {
        Command fallback = new Command(log, "adb", "push", local.getPath(), remote.getPath());
        deviceFilesystem.mkdirs(remote.getParentFile());
        // don't yet cache directories (only used by jtreg tests)
        if (pushCache != null && local.isFile()) {
            String key = pushCache.makeKey(local);
            boolean cacheHit = pushCache.getFromCache(remote, key);
            if (cacheHit) {
                log.verbose("device cache hit for " + local);
                return;
            }
            fallback.execute();
            pushCache.insert(key, remote);
        } else {
            fallback.execute();
        }
    }

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

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

    public void forwardTcp(int port) {
        new Command(log, "adb", "forward", "tcp:" + port, "tcp:" + port).execute();
    }

    public void remount() {
        new Command(log, "adb", "remount").execute();
    }

    public void waitForDevice() {
        new Command(log, "adb", "wait-for-device").execute();
    }

    /**
     * Make sure the directory exists.
     */
    public void ensureDirectory(File path) {
        String pathArgument = path.getPath() + "/";
        if (pathArgument.equals("/sdcard/")) {
            // /sdcard is a mount point. If it exists but is empty we do
            // not want to use it. So we wait until it is not empty.
            waitForNonEmptyDirectory(pathArgument, 5 * 60);
        } else {
            Command command = new Command(log, "adb", "shell", "ls", pathArgument);
            List<String> output = command.execute();
            // TODO: We should avoid checking for the error message, and instead have
            // the Command class understand a non-zero exit code from an adb shell command.
            if (!output.isEmpty()
                && output.get(0).equals(pathArgument + ": No such file or directory")) {
                throw new RuntimeException("'" + pathArgument + "' does not exist on device");
            }
            // Otherwise the directory exists.
        }
    }

    private void waitForNonEmptyDirectory(String pathArgument, int timeoutSeconds) {
        final int millisPerSecond = 1000;
        final long start = System.currentTimeMillis();
        final long deadline = start + (millisPerSecond * timeoutSeconds);

        while (true) {
            final int remainingSeconds =
                    (int) ((deadline - System.currentTimeMillis()) / millisPerSecond);
            Command command = new Command(log, "adb", "shell", "ls", pathArgument);
            List<String> output;
            try {
                output = command.executeWithTimeout(remainingSeconds);
            } catch (TimeoutException e) {
                throw new RuntimeException("Timed out after " + timeoutSeconds
                                           + " seconds waiting for " + pathArgument, e);
            }
            try {
                Thread.sleep(millisPerSecond);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            // We just want any output.
            if (!output.isEmpty()) {
                return;
            }

            log.warn("Waiting on " + pathArgument + " to be mounted ");
        }
    }
}
