/*
 * 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.collect.Iterables;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import vogar.Action;
import vogar.Classpath;
import vogar.Mode;
import vogar.ModeId;
import vogar.Run;
import vogar.Toolchain;
import vogar.Variant;
import vogar.commands.VmCommandBuilder;
import vogar.tasks.MkdirTask;
import vogar.tasks.RunActionTask;
import vogar.tasks.Task;

/**
 * Executes actions on a Dalvik or ART runtime on a Linux desktop.
 */
public final class HostRuntime implements Mode {
    private final Run run;
    private final ModeId modeId;
    private final Variant variant;

    public HostRuntime(Run run, ModeId modeId, Variant variant) {
        if (!modeId.isHost() || !modeId.supportsVariant(variant)) {
            throw new IllegalArgumentException("Unsupported mode:" + modeId +
                    " or variant: " + variant);
        }
        this.run = run;
        this.modeId = modeId;
        this.variant = variant;
    }

    @Override public Task executeActionTask(Action action, boolean useLargeTimeout) {
        return new RunActionTask(run, action, useLargeTimeout);
    }

    private File dalvikCache() {
        return run.localFile("android-data", run.dalvikCache);
    }

    @Override public Set<Task> installTasks() {
        Set<Task> result = new HashSet<Task>();
        for (File classpathElement : run.classpath.getElements()) {
            // Libraries need to be dex'ed and put in the temporary directory.
            String name = run.basenameOfJar(classpathElement);
            File localDex = run.localDexFile(name);
            File localTempDir = run.localDir(name);
            result.add(createCreateDexJarTask(run.classpath, classpathElement, name,
                    null /* action */, localDex, localTempDir));
        }
        result.add(new MkdirTask(run.mkdir, dalvikCache()));
        return result;
    }

    @Override public Set<Task> cleanupTasks(Action action) {
        return Collections.emptySet();
    }

    @Override public Set<Task> installActionTasks(Action action, File jar) {
        File localDexFile = run.localDexFile(action.getName());
        File localTempDir = run.localDir(action.getName());
        Task createDexJarTask = createCreateDexJarTask(Classpath.of(jar), jar, action.getName(),
                action, localDexFile, localTempDir);
        return Collections.singleton(createDexJarTask);
    }

    @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) {
        String hostOut = System.getenv("ANDROID_HOST_OUT");
        if (hostOut == null || hostOut.length() == 0) {
          hostOut = System.getenv("ANDROID_BUILD_TOP");
          if (hostOut == null) {
            hostOut = "";
          } else {
            hostOut += "/";
          }
          hostOut += "out/host/linux-x86";
        }

        List<File> jars = new ArrayList<File>();
        for (String jar : modeId.getJarNames()) {
            jars.add(new File(hostOut, "framework/" + jar + ".jar"));
        }
        Classpath bootClasspath = Classpath.of(jars);

        String libDir = hostOut;
        if (variant == Variant.X32) {
            libDir += "/lib";
        } else if (variant == Variant.DEFAULT || variant == Variant.X64) {
            libDir += "/lib64";
        } else {
            throw new AssertionError("Unsupported variant:" + variant);
        }

        List<String> vmCommand = new ArrayList<String>();
        Iterables.addAll(vmCommand, run.invokeWith());
        vmCommand.add(hostOut + "/bin/" + run.vmCommand);

        // If you edit this, see also DeviceRuntime...
        VmCommandBuilder builder = new VmCommandBuilder(run.log)
                .env("ANDROID_PRINTF_LOG", "tag")
                .env("ANDROID_LOG_TAGS", "*:i")
                .env("ANDROID_DATA", dalvikCache().getParent())
                .env("ANDROID_ROOT", hostOut)
                .env("ANDROID_RUNTIME_ROOT", hostOut + "/com.android.runtime")
                .env("ANDROID_TZDATA_ROOT", hostOut + "/com.android.tzdata")
                .env("LD_LIBRARY_PATH", libDir)
                .env("DYLD_LIBRARY_PATH", libDir)
                // This is needed on the host so that the linker loads core.oat at the necessary
                // address.
                .env("LD_USE_LOAD_BIAS", "1")
                .vmCommand(vmCommand)
                .vmArgs("-Xbootclasspath:" + bootClasspath.toString())
                .vmArgs("-Duser.language=en")
                .vmArgs("-Duser.region=US");
        if (run.debugPort != null) {
            builder.vmArgs(
                    "-Xcompiler-option", "--debuggable", "-Xplugin:libopenjdkjvmti.so",
                    "-agentpath:libjdwp.so=transport=dt_socket,address=" + run.debugPort
                            + ",server=y,suspend=y");
        }
        if (!run.benchmark && run.checkJni) {
            builder.vmArgs("-Xcheck:jni");
        }
        // dalvikvm defaults to no limit, but the framework sets the limit at 2000.
        builder.vmArgs("-Xjnigreflimit:2000");
        return builder;
    }

    @Override public Classpath getRuntimeClasspath(Action action) {
        Classpath result = new Classpath();
        result.addAll(run.localDexFile(action.getName()));
        for (File classpathElement : run.classpath.getElements()) {
            result.addAll(run.localDexFile(run.basenameOfJar(classpathElement)));
        }
        result.addAll(run.resourceClasspath);
        return result;
    }

    private Task createCreateDexJarTask(Classpath classpath, File classpathElement, String name,
            Action action, File localDex, File localTempDir) {
        return new DexTask(run.toolchain.getDexer(), run.androidSdk, classpath, run.benchmark, name,
                classpathElement, action, localDex, localTempDir, run.multidex);
    }
}
