/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.ide.eclipse.adt.internal.launch;

import com.android.ddmuilib.ImageLoader;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode;
import com.android.ide.eclipse.adt.internal.launch.AvdCompatibility.Compatibility;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdkuilib.internal.widgets.AvdSelector;
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter;
import com.android.utils.NullLogger;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * Launch configuration tab to control the parameters of the Emulator
 */
public class EmulatorConfigTab extends AbstractLaunchConfigurationTab {

    private final static String[][] NETWORK_SPEEDS = new String[][] {
        { "Full", "full" }, //$NON-NLS-2$
        { "GSM", "gsm" }, //$NON-NLS-2$
        { "HSCSD", "hscsd" }, //$NON-NLS-2$
        { "GPRS", "gprs" }, //$NON-NLS-2$
        { "EDGE", "edge" }, //$NON-NLS-2$
        { "UMTS", "umts" }, //$NON-NLS-2$
        { "HSPDA", "hsdpa" }, //$NON-NLS-2$
    };

    private final static String[][] NETWORK_LATENCIES = new String[][] {
        { "None", "none" }, //$NON-NLS-2$
        { "GPRS", "gprs" }, //$NON-NLS-2$
        { "EDGE", "edge" }, //$NON-NLS-2$
        { "UMTS", "umts" }, //$NON-NLS-2$
    };

    private Button mAutoTargetButton;
    private Button mManualTargetButton;
    private AvdSelector mPreferredAvdSelector;
    private Combo mSpeedCombo;
    private Combo mDelayCombo;
    private Group mEmulatorOptionsGroup;
    private Text mEmulatorCLOptions;
    private Button mWipeDataButton;
    private Button mNoBootAnimButton;
    private Label mPreferredAvdLabel;
    private IAndroidTarget mProjectTarget;
    private AndroidVersion mProjectMinApiVersion;
    private Button mFutureLaunchesOnSameDevice;
    private boolean mSupportMultiDeviceLaunch;
    private Button mAllDevicesTargetButton;
    private Combo mDeviceTypeCombo;

    private static final String DEVICES_AND_EMULATORS = "Active devices and AVD's";
    private static final String EMULATORS_ONLY = "Active AVD's";
    private static final String DEVICES_ONLY = "Active devices";

    /**
     * Returns the emulator ready speed option value.
     * @param value The index of the combo selection.
     */
    public static String getSpeed(int value) {
        try {
            return NETWORK_SPEEDS[value][1];
        } catch (ArrayIndexOutOfBoundsException e) {
            return NETWORK_SPEEDS[LaunchConfigDelegate.DEFAULT_SPEED][1];
        }
    }

    /**
     * Returns the emulator ready network latency value.
     * @param value The index of the combo selection.
     */
    public static String getDelay(int value) {
        try {
            return NETWORK_LATENCIES[value][1];
        } catch (ArrayIndexOutOfBoundsException e) {
            return NETWORK_LATENCIES[LaunchConfigDelegate.DEFAULT_DELAY][1];
        }
    }

    /**
     *
     */
    public EmulatorConfigTab(boolean supportMultiDeviceLaunch) {
        mSupportMultiDeviceLaunch = supportMultiDeviceLaunch;
    }

    /**
     * @wbp.parser.entryPoint
     */
    @Override
    public void createControl(Composite parent) {
        Font font = parent.getFont();

        // Reload the AVDs to make sure we are up to date
        try {
            // SDK can be null if the user opens the dialog before ADT finished
            // initializing the SDK itself. In this case just don't reload anything
            // so there's nothing obsolete yet.
            Sdk sdk = Sdk.getCurrent();
            if (sdk != null) {
                AvdManager avdMan = sdk.getAvdManager();
                assert avdMan != null;
                avdMan.reloadAvds(NullLogger.getLogger());
            }
        } catch (AndroidLocationException e1) {
            // this happens if the AVD Manager failed to find the folder in which the AVDs are
            // stored. There isn't much we can do at this point.
        }

        Composite topComp = new Composite(parent, SWT.NONE);
        setControl(topComp);
        GridLayout topLayout = new GridLayout();
        topLayout.numColumns = 1;
        topLayout.verticalSpacing = 0;
        topComp.setLayout(topLayout);
        topComp.setFont(font);

        GridData gd;
        GridLayout layout;

        // radio button for the target mode
        Group targetModeGroup = new Group(topComp, SWT.NONE);
        targetModeGroup.setText("Deployment Target Selection Mode");
        gd = new GridData(GridData.FILL_HORIZONTAL);
        targetModeGroup.setLayoutData(gd);
        layout = new GridLayout();
        layout.numColumns = 1;
        targetModeGroup.setLayout(layout);
        targetModeGroup.setFont(font);

        mManualTargetButton = new Button(targetModeGroup, SWT.RADIO);
        mManualTargetButton.setText("Always prompt to pick device");

        mAllDevicesTargetButton = new Button(targetModeGroup, SWT.RADIO);
        mAllDevicesTargetButton.setText("Launch on all compatible devices/AVD's");
        mAllDevicesTargetButton.setEnabled(mSupportMultiDeviceLaunch);

        Composite deviceTypeOffsetComp = new Composite(targetModeGroup, SWT.NONE);
        deviceTypeOffsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        layout = new GridLayout(1, false);
        layout.marginRight = layout.marginHeight = 0;
        layout.marginLeft = 30;
        deviceTypeOffsetComp.setLayout(layout);

        mDeviceTypeCombo = new Combo(deviceTypeOffsetComp, SWT.READ_ONLY);
        mDeviceTypeCombo.setItems(new String[] {
                DEVICES_AND_EMULATORS,
                EMULATORS_ONLY,
                DEVICES_ONLY,
        });
        mDeviceTypeCombo.select(0);
        mDeviceTypeCombo.setEnabled(false);

        // add the radio button
        mAutoTargetButton = new Button(targetModeGroup, SWT.RADIO);
        mAutoTargetButton.setText("Automatically pick compatible device: "
                + "Always uses preferred AVD if set below, "
                + "launches on compatible device/AVD otherwise.");
        mAutoTargetButton.setSelection(true);

        SelectionListener targetModeChangeListener = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                targetModeChanged();
            }
        };

        mAutoTargetButton.addSelectionListener(targetModeChangeListener);
        mAllDevicesTargetButton.addSelectionListener(targetModeChangeListener);
        mManualTargetButton.addSelectionListener(targetModeChangeListener);

        Composite avdOffsetComp = new Composite(targetModeGroup, SWT.NONE);
        avdOffsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        layout = new GridLayout(1, false);
        layout.marginRight = layout.marginHeight = 0;
        layout.marginLeft = 30;
        avdOffsetComp.setLayout(layout);

        mPreferredAvdLabel = new Label(avdOffsetComp, SWT.NONE);
        mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:");

        // create the selector with no manager, we'll reset the manager every time this is
        // displayed to ensure we have the latest one (dialog is reused but SDK could have
        // been changed in between.
        mPreferredAvdSelector = new AvdSelector(avdOffsetComp,
                Sdk.getCurrent().getSdkOsLocation(),
                null /* avd manager */,
                DisplayMode.SIMPLE_CHECK,
                new AdtConsoleSdkLog());
        mPreferredAvdSelector.setTableHeightHint(100);
        SelectionListener listener = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                updateLaunchConfigurationDialog();
            }
        };
        mPreferredAvdSelector.setSelectionListener(listener);
        mDeviceTypeCombo.addSelectionListener(listener);

        mFutureLaunchesOnSameDevice = new Button(targetModeGroup, SWT.CHECK);
        mFutureLaunchesOnSameDevice.setText("Use same device for future launches");
        mFutureLaunchesOnSameDevice.addSelectionListener(listener);

        // emulator size
        mEmulatorOptionsGroup = new Group(topComp, SWT.NONE);
        mEmulatorOptionsGroup.setText("Emulator launch parameters:");
        mEmulatorOptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        layout = new GridLayout();
        layout.numColumns = 2;
        mEmulatorOptionsGroup.setLayout(layout);
        mEmulatorOptionsGroup.setFont(font);

        // Explanation
        Label l = new Label(mEmulatorOptionsGroup, SWT.NONE);
        l.setText("If no compatible and active devices or AVD's are found, then an AVD "
                 + "might be launched. Provide options for the AVD launch below.");
        gd = new GridData();
        gd.horizontalSpan = 2;
        l.setLayoutData(gd);

        // network options
        new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:");

        mSpeedCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);
        for (String[] speed : NETWORK_SPEEDS) {
            mSpeedCombo.add(speed[0]);
        }
        mSpeedCombo.addSelectionListener(listener);
        mSpeedCombo.pack();

        new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Latency:");

        mDelayCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY);

        for (String[] delay : NETWORK_LATENCIES) {
            mDelayCombo.add(delay[0]);
        }
        mDelayCombo.addSelectionListener(listener);
        mDelayCombo.pack();

        // wipe data option
        mWipeDataButton = new Button(mEmulatorOptionsGroup, SWT.CHECK);
        mWipeDataButton.setText("Wipe User Data");
        mWipeDataButton.setToolTipText("Check this if you want to wipe your user data each time you start the emulator. You will be prompted for confirmation when the emulator starts.");
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        mWipeDataButton.setLayoutData(gd);
        mWipeDataButton.addSelectionListener(listener);

        // no boot anim option
        mNoBootAnimButton = new Button(mEmulatorOptionsGroup, SWT.CHECK);
        mNoBootAnimButton.setText("Disable Boot Animation");
        mNoBootAnimButton.setToolTipText("Check this if you want to disable the boot animation. This can help the emulator start faster on slow machines.");
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        mNoBootAnimButton.setLayoutData(gd);
        mNoBootAnimButton.addSelectionListener(listener);

        // custom command line option for emulator
        l = new Label(mEmulatorOptionsGroup, SWT.NONE);
        l.setText("Additional Emulator Command Line Options");
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        l.setLayoutData(gd);

        mEmulatorCLOptions = new Text(mEmulatorOptionsGroup, SWT.BORDER);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        mEmulatorCLOptions.setLayoutData(gd);
        mEmulatorCLOptions.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                updateLaunchConfigurationDialog();
            }
        });
    }

    private void targetModeChanged() {
        updateLaunchConfigurationDialog();

        boolean auto = mAutoTargetButton.getSelection();
        mPreferredAvdSelector.setEnabled(auto);
        mPreferredAvdLabel.setEnabled(auto);

        boolean all = mAllDevicesTargetButton.getSelection();
        mDeviceTypeCombo.setEnabled(all);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
     */
    @Override
    public String getName() {
        return "Target";
    }

    @Override
    public Image getImage() {
        return ImageLoader.getDdmUiLibLoader().loadImage("emulator.png", null); //$NON-NLS-1$
    }

    private void updateAvdList(AvdManager avdManager) {
        if (avdManager == null) {
            avdManager = Sdk.getCurrent().getAvdManager();
        }

        mPreferredAvdSelector.setManager(avdManager);
        mPreferredAvdSelector.refresh(false);

        mPreferredAvdSelector.setFilter(new IAvdFilter() {
            @Override
            public void prepare() {
            }

            @Override
            public void cleanup() {
            }

            @Override
            public boolean accept(AvdInfo avd) {
                AvdCompatibility.Compatibility c =
                        AvdCompatibility.canRun(avd, mProjectTarget, mProjectMinApiVersion);
                return (c == Compatibility.NO) ? false : true;
            }
        });
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
     */
    @Override
    public void initializeFrom(ILaunchConfiguration configuration) {
        AvdManager avdManager = Sdk.getCurrent().getAvdManager();

        TargetMode mode = AndroidLaunchConfiguration.parseTargetMode(configuration,
                LaunchConfigDelegate.DEFAULT_TARGET_MODE);

        boolean multipleDevices = mode.isMultiDevice();
        if (multipleDevices && !mSupportMultiDeviceLaunch) {
            // The launch config says to run on multiple devices, but this launch type does not
            // suppport multiple devices. In such a case, switch back to default mode.
            // This could happen if a launch config used for Run is then used for Debug.
            multipleDevices = false;
            mode = LaunchConfigDelegate.DEFAULT_TARGET_MODE;
        }

        mAutoTargetButton.setSelection(mode == TargetMode.AUTO);
        mManualTargetButton.setSelection(mode == TargetMode.MANUAL);
        mAllDevicesTargetButton.setSelection(multipleDevices);

        targetModeChanged();

        boolean reuseLastUsedDevice;
        try {
            reuseLastUsedDevice = configuration.getAttribute(
                    LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false);
        } catch (CoreException ex) {
            reuseLastUsedDevice = false;
        }
        mFutureLaunchesOnSameDevice.setSelection(reuseLastUsedDevice);

        mDeviceTypeCombo.setEnabled(multipleDevices);
        if (multipleDevices) {
            int index = 0;
            if (mode == TargetMode.ALL_EMULATORS) {
                index = 1;
            } else if (mode == TargetMode.ALL_DEVICES) {
                index = 2;
            }
            mDeviceTypeCombo.select(index);
        }

        // look for the project name to get its target.
        String stringValue = "";
        try {
            stringValue = configuration.getAttribute(
                    IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, stringValue);
        } catch (CoreException ce) {
            // let's not do anything here, we'll use the default value
        }

        IProject project = null;

        // get the list of existing Android projects from the workspace.
        IJavaProject[] projects = BaseProjectHelper.getAndroidProjects(null /*filter*/);
        if (projects != null) {
            // look for the project whose name we read from the configuration.
            for (IJavaProject p : projects) {
                if (p.getElementName().equals(stringValue)) {
                    project = p.getProject();
                    break;
                }
            }
        }

        // update the AVD list
        if (project != null) {
            mProjectTarget = Sdk.getCurrent().getTarget(project);

            ManifestInfo mi = ManifestInfo.get(project);
            final int minApiLevel = mi.getMinSdkVersion();
            final String minApiCodeName = mi.getMinSdkCodeName();
            mProjectMinApiVersion = new AndroidVersion(minApiLevel, minApiCodeName);
        }

        updateAvdList(avdManager);

        stringValue = "";
        try {
            stringValue = configuration.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME,
                    stringValue);
        } catch (CoreException e) {
            // let's not do anything here, we'll use the default value
        }

        if (stringValue != null && stringValue.length() > 0 && avdManager != null) {
            AvdInfo targetAvd = avdManager.getAvd(stringValue, true /*validAvdOnly*/);
            mPreferredAvdSelector.setSelection(targetAvd);
        } else {
            mPreferredAvdSelector.setSelection(null);
        }

        boolean value = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
        try {
            value = configuration.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, value);
        } catch (CoreException e) {
            // let's not do anything here, we'll use the default value
        }
        mWipeDataButton.setSelection(value);

        value = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM;
        try {
            value = configuration.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, value);
        } catch (CoreException e) {
            // let's not do anything here, we'll use the default value
        }
        mNoBootAnimButton.setSelection(value);

        int index = -1;

        index = LaunchConfigDelegate.DEFAULT_SPEED;
        try {
            index = configuration.getAttribute(LaunchConfigDelegate.ATTR_SPEED,
                    index);
        } catch (CoreException e) {
            // let's not do anything here, we'll use the default value
        }
        if (index == -1) {
            mSpeedCombo.clearSelection();
        } else {
            mSpeedCombo.select(index);
        }

        index = LaunchConfigDelegate.DEFAULT_DELAY;
        try {
            index = configuration.getAttribute(LaunchConfigDelegate.ATTR_DELAY,
                    index);
        } catch (CoreException e) {
            // let's not do anything here, we'll put a proper value in
            // performApply anyway
        }
        if (index == -1) {
            mDelayCombo.clearSelection();
        } else {
            mDelayCombo.select(index);
        }

        String commandLine = null;
        try {
            commandLine = configuration.getAttribute(
                    LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$
        } catch (CoreException e) {
            // let's not do anything here, we'll use the default value
        }
        if (commandLine != null) {
            mEmulatorCLOptions.setText(commandLine);
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    @Override
    public void performApply(ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
                getCurrentTargetMode().toString());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE,
                mFutureLaunchesOnSameDevice.getSelection());
        AvdInfo avd = mPreferredAvdSelector.getSelected();
        if (avd != null) {
            configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, avd.getName());
        } else {
            configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String)null);
        }
        configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
                mSpeedCombo.getSelectionIndex());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
                mDelayCombo.getSelectionIndex());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE,
                mEmulatorCLOptions.getText());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
                mWipeDataButton.getSelection());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM,
                mNoBootAnimButton.getSelection());
   }

    private TargetMode getCurrentTargetMode() {
        if (mAutoTargetButton.getSelection()) {
            return TargetMode.AUTO;
        } else if (mManualTargetButton.getSelection()) {
            return TargetMode.MANUAL;
        } else {
            String selection = mDeviceTypeCombo.getText();
            if (DEVICES_AND_EMULATORS.equals(selection)) {
                return TargetMode.ALL_DEVICES_AND_EMULATORS;
            } else if (DEVICES_ONLY.equals(selection)) {
                return TargetMode.ALL_DEVICES;
            } else if (EMULATORS_ONLY.equals(selection)) {
                return TargetMode.ALL_EMULATORS;
            }
        }

        return TargetMode.AUTO;
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    @Override
    public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
        configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
                LaunchConfigDelegate.DEFAULT_TARGET_MODE.toString());
        configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
                LaunchConfigDelegate.DEFAULT_SPEED);
        configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY,
                LaunchConfigDelegate.DEFAULT_DELAY);
        configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA,
                LaunchConfigDelegate.DEFAULT_WIPE_DATA);
        configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM,
                LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM);

        IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
        String emuOptions = store.getString(AdtPrefs.PREFS_EMU_OPTIONS);
        configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions);
   }
}
