/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;

import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.dialogs.MultiStepConfigureWizardPage.WizardStepContainer;

/**
 * Standard workbench wizard to handle a multi-step page. The
 * wizard is allowed any number of pages before the multi-step
 * page is presented to the user.
 * <p>
 * Example:
 * <pre>
 * IWizard wizard = new MultiStepWizard();
 * WizardDialog dialog = new MultiStepWizardDialog(shell, wizard);
 * dialog.open();
 * </pre>
 * </p>
 */
public abstract class MultiStepWizard extends Wizard {
    private MultiStepWizardDialog wizardDialog;

    private MultiStepReviewWizardPage reviewPage;

    private MultiStepConfigureWizardPage configPage;

    /**
     * Creates an empty wizard
     */
    protected MultiStepWizard() {
        super();
        setNeedsProgressMonitor(true);
    }

    /**
     * Adds any custom pages to the wizard before
     * the multi-step review and configure pages are
     * added.
     */
    protected abstract void addCustomPages();

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public final void addPages() {
        super.addPages();
        addCustomPages();

        reviewPage = new MultiStepReviewWizardPage(
                "multiStepReviewWizardPage", this);//$NON-NLS-1$
        reviewPage.setTitle(getReviewPageTitle());
        reviewPage.setDescription(getReviewPageDescription());
        this.addPage(reviewPage);

        configPage = new MultiStepConfigureWizardPage(
                "multiStepConfigureWizardPage");//$NON-NLS-1$
        configPage.setTitle(getConfigurePageTitle());
        configPage.setDescription(getConfigurePageDescription());
        configPage.setWizardDialog(wizardDialog);
        this.addPage(configPage);
    }

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public boolean canFinish() {
        if (getContainer().getCurrentPage() == reviewPage) {
			return canFinishOnReviewPage();
		} else if (isConfigureStepMode()) {
			return getStepContainer().canWizardFinish();
		} else {
			return false;
		}
    }

    /**
     * Returns whether the wizard wants the Finish button
     * enabled on the review page. Should only happen if
     * there is only one step and that step does not require
     * further interaction with the user. The Next button will
     * be disabled and the instructions updated.
     */
    protected abstract boolean canFinishOnReviewPage();

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public void dispose() {
        super.dispose();
        wizardDialog = null;
    }

    /**
     * Returns the title for the multi-step configure
     * page.
     */
    protected abstract String getConfigurePageTitle();

    /**
     * Returns the description for the multi-step configure
     * page.
     */
    protected abstract String getConfigurePageDescription();

    /**
     * Returns the title for the multi-step review
     * page.
     */
    protected abstract String getReviewPageTitle();

    /**
     * Returns the label used on the finish button to
     * to indicate finishing a step. Can be <code>null</code>
     * if no special label is required.
     * <p>
     * The default implementation is to return the translated
     * label "Finish Step".
     * </p><p>
     * On the last step, the finish button label is changed to
     * be "Finish" and will no be changed.
     * </p>
     */
    protected String getFinishStepLabel(WizardStep[] steps) {
        return IDEWorkbenchMessages.MultiStepWizard_finishLabel;
    }

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public final IWizardPage getPreviousPage(IWizardPage page) {
        if (page == configPage) {
			return null;
		} else {
			return super.getPreviousPage(page);
		}
    }

    /**
     * Returns the description for the multi-step review
     * page.
     */
    protected abstract String getReviewPageDescription();

    /**
     * Returns the container handler for the pages
     * of the step's wizard.
     */
    /* package */WizardStepContainer getStepContainer() {
        return configPage.getStepContainer();
    }

    /**
     * Handles the problem of a missing step wizard.
     * 
     * @return <code>true</code> to retry, <code>false</code> to terminate
     * 		multi step wizard dialog.
     */
    /* package */abstract boolean handleMissingStepWizard(WizardStep step);

    /**
     * Returns whether the wizard is configuring steps
     */
    /* package */boolean isConfigureStepMode() {
        return getContainer().getCurrentPage() == configPage;
    }

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public final boolean performCancel() {
        if (isConfigureStepMode()) {
			return getStepContainer().performCancel();
		} else {
			return true;
		}
    }

    /* (non-Javadoc)
     * Method declared on IWizard.
     */
    public boolean performFinish() {
        // Finish on review page is a shortcut to performing
        // the steps.
        if (getContainer().getCurrentPage() == reviewPage) {
            getContainer().showPage(configPage);
            return false;
        }

        // Does nothing as each step is responsible
        // to complete its work when its wizard is
        // done.
        return true;
    }

    /**
     * Returns the collection of steps for the wizard.
     */
    public final WizardStep[] getSteps() {
        if (reviewPage != null) {
			return reviewPage.getSteps();
		} else {
			return new WizardStep[0];
		}
    }

    /**
     * Sets the collection of steps for the wizard.
     * Ignored if the multi-step review and configure
     * pages are not yet created.
     */
    public final void setSteps(WizardStep[] steps) {
        if (reviewPage != null) {
			reviewPage.setSteps(steps);
		}
        if (configPage != null) {
			configPage.setSteps(steps);
		}
    }

    /**
     * Sets the multi-step wizard dialog processing this
     * wizard.
     */
    /* package */void setWizardDialog(MultiStepWizardDialog dialog) {
        wizardDialog = dialog;
        if (configPage != null) {
			configPage.setWizardDialog(wizardDialog);
		}
    }
}
