package org.eclipse.wst.common.frameworks.internal.datamodel.ui;

/*
 * Licensed Material - Property of IBM (C) Copyright IBM Corp. 2001, 2002 - All Rights Reserved. US
 * Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP
 * Schedule Contract with IBM Corp.
 */
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.common.frameworks.datamodel.DataModelEvent;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelListener;
import org.eclipse.wst.common.frameworks.internal.ui.ValidationStatus;

/**
 * This class is EXPERIMENTAL and is subject to substantial changes.
 */
public abstract class DataModelWizardPage extends WizardPage implements Listener, IDataModelListener {
	protected static final int NEXT = 1;
	protected static final int PREVIOUS = 2;
	protected static final int COMPOSITE_BORDER = SWT.NULL;
	private ValidationStatus status = new ValidationStatus();
	private boolean isValidating = false;
	protected boolean isFirstTimeToPage = true;
	protected IDataModel model;
	private Map validationMap;
	private String[] validationPropertyNames;
	protected DataModelSynchHelper synchHelper;
	private String infopopID;

	/**
	 * J2EEWizardPage constructor comment.
	 * 
	 * @param pageName
	 *            java.lang.String
	 */
	protected DataModelWizardPage(IDataModel model, String pageName) {
		super(pageName);
		this.model = model;
		model.addListener(this);
		synchHelper = initializeSynchHelper(model);
	}

	/**
	 * @return
	 */
	public DataModelSynchHelper initializeSynchHelper(IDataModel dm) {
		return new DataModelSynchHelper(dm);
	}

	/**
	 * J2EEWizardPage constructor comment.
	 * 
	 * @param pageName
	 *            java.lang.String
	 * @param title
	 *            java.lang.String
	 * @param titleImage
	 *            org.eclipse.jface.resource.ImageDescriptor
	 */
	protected DataModelWizardPage(IDataModel model, String pageName, String title, org.eclipse.jface.resource.ImageDescriptor titleImage) {
		super(pageName, title, titleImage);
		this.model = model;
		model.addListener(this);
		synchHelper = initializeSynchHelper(model);
	}

	/**
	 * Creates the top level control for this dialog page under the given parent composite. This
	 * method has been abstract and it uses the template pattern to get the correct items setup in
	 * the correct order. See the set of methods below that are called in this method.
	 * <p>
	 * Implementors are responsible for ensuring that the created control can be accessed via
	 * <code>getControl</code>
	 * </p>
	 * 
	 * @param parent
	 *            the parent composite
	 */
	public final void createControl(org.eclipse.swt.widgets.Composite parent) {
		Composite top = createTopLevelComposite(parent);
		setControl(top);
		setupInfopop(top);
		setDefaults();
		addListeners();
		initializeValidationProperties();
	}

	private void initializeValidationProperties() {
		validationPropertyNames = getValidationPropertyNames();
		if (validationPropertyNames == null || validationPropertyNames.length == 0)
			validationMap = Collections.EMPTY_MAP;
		else {
			validationMap = new HashMap(validationPropertyNames.length);
			for (int i = 0; i < validationPropertyNames.length; i++)
				validationMap.put(validationPropertyNames[i], new Integer(i));
		}
	}

	/**
	 * Subclass should return the model property names that need to be validated on this page in the
	 * order that they should present their messages.
	 * 
	 * @return
	 */
	protected abstract String[] getValidationPropertyNames();

	/**
	 * Return the top level Composite for this page.
	 */
	protected abstract Composite createTopLevelComposite(Composite parent);

	/**
	 * Set up info pop hooks if set.
	 */
	protected void setupInfopop(Control parent) {
		if (getInfopopID() != null)
			PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, getInfopopID());
	}

	/**
	 * Setup the default values for this page. Subclasses should override to provide appropriate
	 * defaults.
	 */
	protected void setDefaults() {
		restoreDefaultSettings();
	}

	/**
	 * Subclasses should implement this method if they have default settings that have been stored
	 * and need to be restored.
	 * 
	 * @see storeDefaultSettings()
	 */
	protected void restoreDefaultSettings() {
	}

	/**
	 * Add Listeners to controls at this point to avoid unnecessary events. Subclasses should
	 * override to add listeners to its controls.
	 */
	protected void addListeners() {
	}

	/**
	 * The page is being made current and visible. Subclasses may extend.
	 */
	protected void enter() {
		try {
			validatePage(showValidationErrorsOnEnter());
		} finally {
			isFirstTimeToPage = false;
		}
	}

	/**
	 * The default behavior is to return true unless it is the first time entering this page in
	 * which case we check to see if there is a previous page and return true if there is not.
	 * Subclasses should override if they do not want this default behavior.
	 */
	protected boolean showValidationErrorsOnEnter() {
		return !isFirstTimeToPage();
	}

	/**
	 * The default behavior is to return true unless it is the first time entering this page in
	 * which case we check to see if there is a previous page and return true if there is not.
	 * Subclasses should override if they do not want this default behavior.
	 * 
	 * @deprecated - use showValidatoinErrorsOnEnter instead
	 */
	protected boolean shouldValidateOnEnter() {
		return showValidationErrorsOnEnter();
	}

	/**
	 * Exiting the page. Subclasses may extend.
	 */
	protected void exit() {
	}

	protected boolean getStatus(Integer key) {
		return status.hasError(key);
	}

	/**
	 * Sent when an event that the receiver has registered for occurs. If a subclass overrides this
	 * method, it must call super.
	 * 
	 * @param event
	 *            the event which occurred
	 */
	public void handleEvent(org.eclipse.swt.widgets.Event event) {
	}

	/**
	 * Set the error message for this page based on the last error in the ValidationStatus.
	 */
	protected void setErrorMessage() {
		String error = status.getLastErrMsg();
		if (error == null) {
			if (getErrorMessage() != null)
				setErrorMessage((String) null);
			String warning = status.getLastWarningMsg();
			if (warning == null) {
				if (getMessage() != null && getMessageType() == IMessageProvider.WARNING)
					setMessage(null, IMessageProvider.WARNING);
			} else if (!warning.equals(getMessage()))
				setMessage(warning, IMessageProvider.WARNING);
		} else if (!error.equals(getErrorMessage()))
			setErrorMessage(error);
	}

	protected void setErrorStatus(Integer key, String errorMessage) {
		status.setErrorStatus(key, errorMessage);
	}

	protected void setWarningStatus(Integer key, String warningMessage) {
		status.setWarningStatus(key, warningMessage);
	}

	protected void setOKStatus(Integer key) {
		status.setOKStatus(key);
	}

	/**
	 * The <code>DialogPage</code> implementation of this <code>IDialogPage</code> method sets
	 * the control to the given visibility state. Subclasses may extend.
	 */

	public void setVisible(boolean visible) {
		super.setVisible(visible);
		if (visible) {
			Rectangle workbenchBounds = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getBounds();
			int newX = workbenchBounds.x + workbenchBounds.width/2;
			int newY = workbenchBounds.y + workbenchBounds.height/2;
			Point p = getShell().computeSize(SWT.DEFAULT,SWT.DEFAULT);
			getShell().setBounds(newX - p.x/2, newY - p.y/2,p.x,p.y);
			enter();
		}
		else
			exit();
	}

	/**
	 * This should be called by the Wizard just prior to running the performFinish operation.
	 * Subclasses should override to store their default settings.
	 */
	public void storeDefaultSettings() {
	}

	/**
	 * The page is now being validated. At this time, each control is validated and then the
	 * controls are updated based on the results in the ValidationStatus which was updated during
	 * <code>validateControls()</code>. Finally, it will display the last error message and it
	 * will set the page complete. Subclasses will not typically override this method.
	 */
	protected void validatePage() {
		validatePage(true);
	}

	protected void validatePage(boolean showMessage) {
		if (!isValidating) {
			isValidating = true;
			try {
				validateControlsBase();
				updateControls();
				if (showMessage)
					setErrorMessage();
				setPageComplete(status.getLastErrMsg() == null);
			} finally {
				isValidating = false;
			}
		}
	}

	/**
	 * Validate individual controls. Use validation keys to keep track of errors.
	 * 
	 * @see setOKStatus(Integer) and setErrorMessage(Integer, String)
	 */
	protected final String validateControlsBase() {
		if (!validationMap.isEmpty()) {
			String propName;
			for (int i = 0; i < validationPropertyNames.length; i++) {
				propName = validationPropertyNames[i];
				Integer valKey = (Integer) validationMap.get(propName);
				if (valKey != null)
					validateProperty(propName, valKey);
				if (!getStatus(valKey))
					return propName;
			}
		}
		return null;
	}

	/**
	 * @param propertyName
	 * @param validationkey
	 */
	private void validateProperty(String propertyName, Integer validationKey) {
		setOKStatus(validationKey);
		IStatus status1 = model.validateProperty(propertyName);
		if (!status1.isOK()) {
			String message = status1.isMultiStatus() ? status1.getChildren()[0].getMessage() : status1.getMessage();
			switch (status1.getSeverity()) {
				case IStatus.ERROR :
					setErrorStatus(validationKey, message);
					break;
				case IStatus.WARNING :
					setWarningStatus(validationKey, message);
					break;
			}
		}
	}

	/**
	 * Update the enablement of controls after validation. Sublcasses should check the status of
	 * validation keys to determine enablement.
	 */
	protected void updateControls() {
	}

	/**
	 * Gets the isFirstTimeToPage.
	 * 
	 * @return Returns a boolean
	 */
	protected boolean isFirstTimeToPage() {
		return isFirstTimeToPage;
	}

	// protected void setJavaStatusMessage(IStatus javaStatus, Integer statusKey, String message) {
	// if (javaStatus.getSeverity() == IStatus.WARNING)
	// setWarningStatus(statusKey, message);
	// else
	// setErrorStatus(statusKey, message);
	// }

	/**
	 * @param b
	 */
	public void setFirstTimeToPage(boolean b) {
		isFirstTimeToPage = b;
	}

	/*
	 * If a property changes that we want to validate, force validation on this page.
	 * 
	 * @see org.eclipse.wst.common.frameworks.internal.operation.WTPOperationDataModelListener#propertyChanged(java.lang.String,
	 *      java.lang.Object, java.lang.Object)
	 */
	public void propertyChanged(DataModelEvent event) {
		String propertyName = event.getPropertyName();
		if (validationPropertyNames != null && (event.getFlag() == DataModelEvent.VALUE_CHG || (!isPageComplete() && event.getFlag() == DataModelEvent.VALID_VALUES_CHG))) {
			for (int i = 0; i < validationPropertyNames.length; i++) {
				if (validationPropertyNames[i].equals(propertyName)) {
					validatePage();
					break;
				}
			}
		}
	}

	/**
	 * @return Returns the model.
	 */
	protected IDataModel getDataModel() {
		return model;
	}

	public void dispose() {
		super.dispose();
		if (synchHelper != null) {
			synchHelper.dispose();
			synchHelper = null;
		}
	}

	protected String getInfopopID() {
		return infopopID;
	}

	public void setInfopopID(String infopopID) {
		this.infopopID = infopopID;
	}
}