/*
 * Copyright (C) 2015 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 com.android.preload;

import com.android.ddmlib.Client;
import com.android.ddmlib.IDevice;
import com.android.preload.actions.ClearTableAction;
import com.android.preload.actions.ComputeThresholdAction;
import com.android.preload.actions.ComputeThresholdXAction;
import com.android.preload.actions.DeviceSpecific;
import com.android.preload.actions.ExportAction;
import com.android.preload.actions.ImportAction;
import com.android.preload.actions.ReloadListAction;
import com.android.preload.actions.RunMonkeyAction;
import com.android.preload.actions.ScanAllPackagesAction;
import com.android.preload.actions.ScanPackageAction;
import com.android.preload.actions.ShowDataAction;
import com.android.preload.classdataretrieval.ClassDataRetriever;
import com.android.preload.classdataretrieval.hprof.Hprof;
import com.android.preload.classdataretrieval.jdwp.JDWPClassDataRetriever;
import com.android.preload.ui.IUI;
import com.android.preload.ui.SequenceUI;
import com.android.preload.ui.SwingUI;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.swing.Action;
import javax.swing.DefaultListModel;

public class Main {

    /**
     * Enable tracing mode. This is a work-in-progress to derive compiled-methods data, so it is
     * off for now.
     */
    public final static boolean ENABLE_TRACING = false;

    /**
     * Ten-second timeout.
     */
    public final static int DEFAULT_TIMEOUT_MILLIS = 10 * 1000;

    /**
     * Hprof timeout. Two minutes.
     */
    public final static int HPROF_TIMEOUT_MILLIS = 120 * 1000;

    private IDevice device;
    private static ClientUtils clientUtils;

    private DumpTableModel dataTableModel;
    private DefaultListModel<Client> clientListModel;

    private IUI ui;

    // Actions that need to be updated once a device is selected.
    private Collection<DeviceSpecific> deviceSpecificActions;

    // Current main instance.
    private static Main top;
    private static boolean useJdwpClassDataRetriever = false;

    public final static String CLASS_PRELOAD_BLACKLIST = "android.app.AlarmManager$" + "|"
            + "android.app.SearchManager$" + "|" + "android.os.FileObserver$" + "|"
            + "com.android.server.PackageManagerService\\$AppDirObserver$" + "|" +


            // Threads
            "android.os.AsyncTask$" + "|" + "android.pim.ContactsAsyncHelper$" + "|"
            + "android.webkit.WebViewClassic\\$1$" + "|" + "java.lang.ProcessManager$" + "|"
            + "(.*\\$NoPreloadHolder$)";

    public final static String SCAN_ALL_CMD = "scan-all";
    public final static String SCAN_PACKAGE_CMD = "scan";
    public final static String COMPUTE_FILE_CMD = "comp";
    public final static String EXPORT_CMD = "export";
    public final static String IMPORT_CMD = "import";

    /**
     * @param args
     */
    public static void main(String[] args) {
        Main m;
        if (args.length > 0 && args[0].equals("--seq")) {
            m = createSequencedMain(args);
        } else {
            m = new Main(new SwingUI());
        }

        top = m;
        m.startUp();
    }

    public Main(IUI ui) {
        this.ui = ui;

        clientListModel = new DefaultListModel<Client>();
        dataTableModel = new DumpTableModel();

        clientUtils = new ClientUtils(DEFAULT_TIMEOUT_MILLIS);  // Client utils with 10s timeout.

        List<Action> actions = new ArrayList<Action>();
        actions.add(new ReloadListAction(clientUtils, null, clientListModel));
        actions.add(new ClearTableAction(dataTableModel));
        actions.add(new RunMonkeyAction(null, dataTableModel));
        actions.add(new ScanPackageAction(clientUtils, null, dataTableModel));
        actions.add(new ScanAllPackagesAction(clientUtils, null, dataTableModel));
        actions.add(new ComputeThresholdAction("Compute preloaded-classes", dataTableModel, 2,
                CLASS_PRELOAD_BLACKLIST));
        actions.add(new ComputeThresholdAction("Compute compiled-classes", dataTableModel, 1,
                null));
        actions.add(new ComputeThresholdXAction("Compute(X)", dataTableModel,
                CLASS_PRELOAD_BLACKLIST));
        actions.add(new ShowDataAction(dataTableModel));
        actions.add(new ImportAction(dataTableModel));
        actions.add(new ExportAction(dataTableModel));

        deviceSpecificActions = new ArrayList<DeviceSpecific>();
        for (Action a : actions) {
            if (a instanceof DeviceSpecific) {
                deviceSpecificActions.add((DeviceSpecific)a);
            }
        }

        ui.prepare(clientListModel, dataTableModel, actions);
    }

    /**
     * @param args
     * @return
     */
    private static Main createSequencedMain(String[] args) {
        SequenceUI ui = new SequenceUI();
        Main main = new Main(ui);

        Iterator<String> it = Arrays.asList(args).iterator();
        it.next();  // --seq
        // Setup
        ui.choice("#" + it.next());  // Device.
        ui.confirmNo();              // Prepare: no.
        // Actions
        try {
            while (it.hasNext()) {
                String op = it.next();
                // Operation: Scan a single package
                if (SCAN_PACKAGE_CMD.equals(op)) {
                    System.out.println("Scanning package.");
                    ui.action(ScanPackageAction.class);
                    ui.client(it.next());
                // Operation: Scan all packages
                } else if (SCAN_ALL_CMD.equals(op)) {
                    System.out.println("Scanning all packages.");
                    ui.action(ScanAllPackagesAction.class);
                // Operation: Export the output to a file
                } else if (EXPORT_CMD.equals(op)) {
                    System.out.println("Exporting data.");
                    ui.action(ExportAction.class);
                    ui.output(new File(it.next()));
                // Operation: Import the input from a file or directory
                } else if (IMPORT_CMD.equals(op)) {
                    System.out.println("Importing data.");
                    File file = new File(it.next());
                    if (!file.exists()) {
                        throw new RuntimeException(
                                String.format("File does not exist, %s.", file.getAbsolutePath()));
                    } else if (file.isFile()) {
                        ui.action(ImportAction.class);
                        ui.input(file);
                    } else if (file.isDirectory()) {
                        for (File content : file.listFiles()) {
                            ui.action(ImportAction.class);
                            ui.input(content);
                        }
                    }
                // Operation: Compute preloaded classes with specific threshold
                } else if (COMPUTE_FILE_CMD.equals(op)) {
                    System.out.println("Compute preloaded classes.");
                    ui.action(ComputeThresholdXAction.class);
                    ui.input(it.next());
                    ui.confirmYes();
                    ui.output(new File(it.next()));
                }
            }
        } catch (NoSuchElementException e) {
            System.out.println("Failed to parse action sequence correctly.");
            throw e;
        }

        return main;
    }

    public static IUI getUI() {
        return top.ui;
    }

    public static ClassDataRetriever getClassDataRetriever() {
        if (useJdwpClassDataRetriever) {
            return new JDWPClassDataRetriever();
        } else {
            return new Hprof(HPROF_TIMEOUT_MILLIS);
        }
    }

    public IDevice getDevice() {
        return device;
    }

    public void setDevice(IDevice device) {
        this.device = device;
        for (DeviceSpecific ds : deviceSpecificActions) {
            ds.setDevice(device);
        }
    }

    public DefaultListModel<Client> getClientListModel() {
        return clientListModel;
    }

    static class DeviceWrapper {
        IDevice device;

        public DeviceWrapper(IDevice d) {
            device = d;
        }

        @Override
        public String toString() {
            return device.getName() + " (#" + device.getSerialNumber() + ")";
        }
    }

    private void startUp() {
        getUI().showWaitDialog();
        initDevice();

        // Load clients.
        new ReloadListAction(clientUtils, getDevice(), clientListModel).run();

        getUI().hideWaitDialog();
        getUI().ready();
    }

    private void initDevice() {
        DeviceUtils.init(DEFAULT_TIMEOUT_MILLIS);

        IDevice devices[] = DeviceUtils.findDevices(DEFAULT_TIMEOUT_MILLIS);
        if (devices == null || devices.length == 0) {
            throw new RuntimeException("Could not find any devices...");
        }

        getUI().hideWaitDialog();

        DeviceWrapper deviceWrappers[] = new DeviceWrapper[devices.length];
        for (int i = 0; i < devices.length; i++) {
            deviceWrappers[i] = new DeviceWrapper(devices[i]);
        }

        DeviceWrapper ret = Main.getUI().showChoiceDialog("Choose a device", "Choose device",
                deviceWrappers);
        if (ret != null) {
            setDevice(ret.device);
        } else {
            System.exit(0);
        }

        boolean prepare = Main.getUI().showConfirmDialog("Prepare device?",
                "Do you want to prepare the device? This is highly recommended.");
        if (prepare) {
            String buildType = DeviceUtils.getBuildType(device);
            if (buildType == null || (!buildType.equals("userdebug") && !buildType.equals("eng"))) {
                Main.getUI().showMessageDialog("Need a userdebug or eng build! (Found " + buildType
                        + ")");
                return;
            }
            if (DeviceUtils.hasPrebuiltBootImage(device)) {
                Main.getUI().showMessageDialog("Cannot prepare a device with pre-optimized boot "
                        + "image!");
                return;
            }

            if (ENABLE_TRACING) {
                DeviceUtils.enableTracing(device);
            }

            Main.getUI().showMessageDialog("The device will reboot. This will potentially take a "
                    + "long time. Please be patient.");
            if (!DeviceUtils.removePreloaded(device, 15 * 60) /* 15m timeout */) {
                Main.getUI().showMessageDialog("Removing preloaded-classes failed unexpectedly!");
            }
        }
    }

    public static Map<String, String> findAndGetClassData(IDevice device, String packageName)
            throws Exception {
        Client client = clientUtils.findClient(device, packageName, -1);
        if (client == null) {
            throw new RuntimeException("Could not find client...");
        }
        System.out.println("Found client: " + client);

        return getClassDataRetriever().getClassData(client);
    }

}
