/*
 * Copyright (C) 2011 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.welcome;

import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;
import com.android.sdkstats.DdmsPreferenceStore;
import com.android.sdkuilib.internal.repository.sdkman2.AdtUpdateDialog;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

/**
 * Wizard shown on first start for new users: configure SDK location, accept or
 * reject usage data collection, etc
 */
public class WelcomeWizard extends Wizard {
    private final DdmsPreferenceStore mStore;
    private WelcomeWizardPage mWelcomePage;
    private UsagePermissionPage mUsagePage;

    /**
     * Creates a new {@link WelcomeWizard}
     *
     * @param store preferences for usage statistics collection etc
     */
    public WelcomeWizard(DdmsPreferenceStore store) {
        mStore = store;

        setWindowTitle("Welcome to Android Development");
        ImageDescriptor image = AdtPlugin.getImageDescriptor("icons/android-64.png"); //$NON-NLS-1$
        setDefaultPageImageDescriptor(image);
    }

    @Override
    public void addPages() {
        mWelcomePage = new WelcomeWizardPage();
        addPage(mWelcomePage);

        // It's possible that the user has already run the command line tools
        // such as ddms and has agreed to usage statistics collection, but has never
        // run ADT which is why the wizard was opened. No need to ask again.
        if (!mStore.isPingOptIn()) {
            mUsagePage = new UsagePermissionPage();
            addPage(mUsagePage);
        }
    }

    @Override
    public boolean performFinish() {
        if (mUsagePage != null) {
            boolean isUsageCollectionApproved = mUsagePage.isUsageCollectionApproved();
            DdmsPreferenceStore store = new DdmsPreferenceStore();

            // Workaround: Store a new ping id if one doesn't exist, regardless of
            // whether usage statistics gathering is enabled, to ensure that ddms and
            // ADT agree upon whether usage data collection is enabled. The reason this
            // is necessary is that the Eclipse PreferenceStore optimizes out writing
            // property values that equal their default values, and in our case, the
            // default value for usage-collection is "false", so it just doesn't write
            // it into the config file is the user opts out - which means that nothing
            // is written in ddms.config. That works in the sense that the getter returns
            // "usage collection"=false, but it doesn't work in the sense that it looks
            // like the property has not yet been decided by the user. DDMS will look at
            // the existence of a ping id to see whether we've already considered the
            // question, so do the same here.
            if (!store.hasPingId()) {
                store.generateNewPingId();
            }

            store.setPingOptIn(isUsageCollectionApproved);
        }

        // Read out wizard settings immediately; we will perform the actual work
        // after the wizard window has been taken down and it's too late to read the
        // settings then
        final File path = mWelcomePage.getPath();
        final boolean installCommon = mWelcomePage.isInstallCommon();
        final boolean installLatest = mWelcomePage.isInstallLatest();
        final boolean createNew = mWelcomePage.isCreateNew();

        // Perform installation asynchronously since it takes a while.
        getShell().getDisplay().asyncExec(new Runnable() {
            public void run() {
                if (createNew) {
                    try {
                        Set<Integer> apiLevels = new HashSet<Integer>();
                        if (installCommon) {
                            apiLevels.add(7);
                        }
                        if (installLatest) {
                            apiLevels.add(AdtUpdateDialog.USE_MAX_REMOTE_API_LEVEL);
                        }
                        installSdk(path, apiLevels);
                    } catch (Exception e) {
                        AdtPlugin.logAndPrintError(e, "ADT Welcome Wizard", "Installation failed");
                    }
                }

                // Set SDK path after installation since this will trigger a SDK refresh.
                AdtPrefs.getPrefs().setSdkLocation(path);
            }
        });

        // The wizard always succeeds, even if installation fails or is aborted
        return true;
    }

    /**
     * Trigger the install window. It will connect to the repository, display
     * a confirmation window showing which packages are selected for install
     * and display a progress dialog during installation.
     */
    private boolean installSdk(File path, Set<Integer> apiLevels) {
        if (!path.isDirectory()) {
            if (!path.mkdirs()) {
                AdtPlugin.logAndPrintError(null, "ADT Welcome Wizard",
                        "Failed to create directory %1$s",
                        path.getAbsolutePath());
                return false;
            }
        }

        // Get a shell to use for the SDK installation. There are cases where getActiveShell
        // returns null so attempt to obtain it through other means.
        Display display = AdtPlugin.getDisplay();
        Shell shell = display.getActiveShell();
        if (shell == null) {
            IWorkbench workbench = PlatformUI.getWorkbench();
            IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
            if (window != null) {
                shell = window.getShell();
            }
        }
        boolean disposeShell = false;
        if (shell == null) {
            shell = new Shell(display);
            AdtPlugin.log(IStatus.WARNING, "No parent shell for SDK installation dialog");
            disposeShell = true;
        }

        AdtUpdateDialog updater = new AdtUpdateDialog(
                shell,
                new AdtConsoleSdkLog(),
                path.getAbsolutePath());
        // Note: we don't have to specify tools & platform-tools since they
        // are required dependencies of any platform.
        boolean result = updater.installNewSdk(apiLevels);

        if (disposeShell) {
            shell.dispose();
        }

        if (!result) {
            AdtPlugin.printErrorToConsole("Failed to install Android SDK.");
            return false;
        }

        return true;
    }
}
