/*
 * Copyright (C) 2009 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.base.Supplier;
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.Toolchain;
import vogar.Variant;
import vogar.Classpath;
import vogar.Mode;
import vogar.ModeId;
import vogar.Run;
import vogar.commands.VmCommandBuilder;
import vogar.tasks.RunActionTask;
import vogar.tasks.Task;

/**
 * Execute actions on an Android device or emulator using "app_process" or the runtime directly.
 */
public final class DeviceRuntime implements Mode {
    private final Run run;
    private final ModeId modeId;
    private final Supplier<String> deviceUserNameSupplier;

    public DeviceRuntime(Run run, ModeId modeId, Variant variant,
                         Supplier<String> deviceUserNameSupplier) {
        this.deviceUserNameSupplier = deviceUserNameSupplier;
        if (!modeId.isDevice() || !modeId.supportsVariant(variant)) {
            throw new IllegalArgumentException("Unsupported mode:" + modeId +
                    " or variant: " + variant);
        }
        this.run = run;
        this.modeId = modeId;
    }

    @Override public Set<Task> installTasks() {
        Set<Task> result = new HashSet<Task>();
        // dex everything on the classpath and push it to the device.
        for (File classpathElement : run.classpath.getElements()) {
            addCreateDexJarAndPushTasks(result, run.basenameOfJar(classpathElement),
                    classpathElement, null);
        }
        return result;
    }

    @Override public Set<Task> installActionTasks(Action action, File jar) {
        Set<Task> result = new HashSet<Task>();
        addCreateDexJarAndPushTasks(result, action.getName(), jar, action);
        return result;
    }

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

    @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) {
        List<String> vmCommand = new ArrayList<String>();
        Iterables.addAll(vmCommand, run.invokeWith());
        vmCommand.add(run.vmCommand);

        // If you edit this, see also HostRuntime...
        VmCommandBuilder vmCommandBuilder = new VmCommandBuilder(run.log)
                .env("ANDROID_DATA", run.getAndroidDataPath())
                .workingDirectory(workingDirectory)
                .vmCommand(vmCommand)
                .vmArgs("-Duser.home=" + run.deviceUserHome)
                // Use the same command line limit (4096) as adb (see
                // _adb_connect in system/core/adb/adb_client.cpp).
                .maxLength(4096);
        if (run.debugPort != null) {
            vmCommandBuilder.vmArgs("-Xcompiler-option", "--debuggable");
        }

        if (modeId == ModeId.APP_PROCESS) {
            return vmCommandBuilder
                .vmArgs(action.getUserDir().getPath())
                .classpathViaProperty(true);
        }

        vmCommandBuilder
                .vmArgs("-Duser.name=" + deviceUserNameSupplier.get())
                .vmArgs("-Duser.language=en")
                .vmArgs("-Duser.region=US");

        if (!run.benchmark && run.checkJni) {
            vmCommandBuilder.vmArgs("-Xcheck:jni");
        }
        // dalvikvm defaults to no limit, but the framework sets the limit at 2000.
        vmCommandBuilder.vmArgs("-Xjnigreflimit:2000");
        return vmCommandBuilder;
    }

    @Override public Set<Task> cleanupTasks(Action action) {
        return Collections.singleton(run.target.rmTask(action.getUserDir()));
    }

    @Override public Classpath getRuntimeClasspath(Action action) {
        Classpath result = new Classpath();
        result.addAll(run.targetDexFile(action.getName()));
        if (!run.benchmark) {
            for (File classpathElement : run.classpath.getElements()) {
                result.addAll(run.targetDexFile(run.basenameOfJar(classpathElement)));
            }
        }
        // Note we intentionally do not add run.resourceClasspath on
        // the device since it contains host path names.
        return result;
    }

    private void addCreateDexJarAndPushTasks(
            Set<Task> tasks, String name, File jar, Action action) {
        File localDex = run.localDexFile(name);
        File localTempDir = run.localDir(name);
        File deviceDex = run.targetDexFile(name);
        Task createDexJarTask = newCreateDexJarTask(run.classpath, jar, name, action, localDex,
                localTempDir);
        tasks.add(createDexJarTask);
        tasks.add(run.target.pushTask(localDex, deviceDex).afterSuccess(createDexJarTask));
    }

    private Task newCreateDexJarTask(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);
    }
}
