//------------------------------------------------------------------------------
// Copyright (c) 2005, 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.wizards;

import java.util.Iterator;
import java.util.List;

import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.AuthoringUIText;
import org.eclipse.epf.library.ui.LibraryUIImages;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ModelStorage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;


/**
 * A wizard page that prompts the user to enter a name and description for a new
 * Method Plug-in.
 * 
 * @author Shashidhar Kannoori
 * @author Kelvin Low
 * @since 1.0
 */
public class NewMethodPluginWizardPage extends WizardPage implements Listener {

	/**
	 * The wizard page name.
	 */
	public static final String PAGE_NAME = NewMethodPluginWizardPage.class
			.getName();

	protected Text nameText;

	private Text briefDescText;

	private Text authorsText;

	private CheckboxTableViewer referencedPluginsViewer;

	private List plugins;

	/**
	 * Creates a new instance.
	 */
	public NewMethodPluginWizardPage() {
		super(PAGE_NAME);
		setTitle(AuthoringUIResources.newPluginWizardPage_title); //$NON-NLS-1$
		setDescription(AuthoringUIResources.newPluginWizardPage_text); //$NON-NLS-1$
		setImageDescriptor(AuthoringUIPlugin.getDefault().getImageDescriptor(
				"full/wizban/New.gif")); //$NON-NLS-1$		
	}

	/**
	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(Composite)
	 */
	public void createControl(Composite parent) {
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		GridData labelGridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);

		Composite composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout(2, false));
		composite.setLayoutData(gridData);

		Label nameLabel = new Label(composite, SWT.NONE);
		nameLabel.setText(AuthoringUIText.NAME_TEXT);
		nameText = new Text(composite, SWT.BORDER);
		// TODO: Provide a unique default plug-in name.
		nameText.setText("new_plug-in"); //$NON-NLS-1$
		nameText.setLayoutData(gridData);

		Label briefDescLabel = new Label(composite, SWT.NONE);
		briefDescLabel.setText(AuthoringUIText.BRIEF_DESCRIPTION_TEXT);
		briefDescLabel.setLayoutData(labelGridData);
		briefDescText = new Text(composite, SWT.BORDER | SWT.MULTI | SWT.WRAP
				| SWT.V_SCROLL);
		GridData briefDescGridData = new GridData(GridData.FILL_HORIZONTAL);
		briefDescGridData.heightHint = 70;
		briefDescText.setLayoutData(briefDescGridData);

		Label authorsLabel = new Label(composite, SWT.NONE);
		authorsLabel.setText(AuthoringUIText.AUTHORS_TEXT);
		authorsLabel.setLayoutData(labelGridData);
		authorsText = new Text(composite, SWT.BORDER | SWT.MULTI | SWT.WRAP
				| SWT.V_SCROLL);
		GridData authorsGridData = new GridData(GridData.FILL_HORIZONTAL);
		authorsGridData.heightHint = 35;
		authorsText.setLayoutData(authorsGridData);

		Label referencedPluginsLabel = new Label(composite, SWT.NONE);
		referencedPluginsLabel
				.setText(AuthoringUIText.REFERENCED_PLUGINS_SECTION_NAME);
		referencedPluginsLabel.setLayoutData(labelGridData);
		plugins = ModelStorage.getBaseModels();
		String[] items = new String[plugins.size()];
		for (int i = 0; i < plugins.size(); i++) {
			MethodPlugin model = (MethodPlugin) plugins.get(i);
			items[i] = model.getName();
		}
		referencedPluginsViewer = CheckboxTableViewer.newCheckList(composite,
				SWT.BORDER | SWT.FILL | SWT.HORIZONTAL);
		GridData referencedPluginsGridData = new GridData(
				GridData.FILL_HORIZONTAL);
		referencedPluginsGridData.heightHint = 150;
		referencedPluginsViewer.getTable().setLayoutData(
				referencedPluginsGridData);

		ILabelProvider labelProvider = new LabelProvider() {

			public Image getImage(Object element) {
				return LibraryUIImages.IMG_METHOD_PLUGIN;
			}

			public String getText(Object element) {
				if (element instanceof MethodPlugin) {
					return ((MethodPlugin) element).getName();
				} else {
					return element.toString();
				}
			}

		};

		referencedPluginsViewer.setLabelProvider(labelProvider);

		if (plugins != null) {
			Iterator it = plugins.iterator();
			while (it.hasNext()) {
				referencedPluginsViewer.add(it.next());
			}
		}

		setControl(composite);

		// Get the parent shell.
		Shell shell = parent.getShell();

		nameText.addListener(SWT.Modify, this);
		nameText.addListener(SWT.FocusOut, this);

		Display display = shell.getDisplay();
		if (display != null && !display.isDisposed()) {
			display.asyncExec(new Runnable() {
				public void run() {
					nameText.setFocus();
					nameText.setSelection(0, nameText.getText().length());
				}
			});
		}
	}

	/**
	 * @see org.eclipse.swt.widgets.Listener#handleEvent(Event)
	 */
	public void handleEvent(Event event) {
		if (event.widget == nameText) {
			validateName();
		}
		setPageComplete(isPageComplete());
		getWizard().getContainer().updateButtons();
	}

	/**
	 * Validate the plug-in name.
	 */
	public boolean validateName() {
		boolean answer;

		String msg = LibraryUtil.checkPluginName(null, getPluginName());
		if (msg == null) {
			answer = true;
			setErrorMessage(null);
			setMessage(AuthoringUIResources.newPluginWizardPage_text); //$NON-NLS-1$
		} else {
			answer = false;
			int idx = msg.indexOf("'."); //$NON-NLS-1$
			if (idx >= 0)
				msg = msg.substring(idx + 3);
			// Check for IUPL0101E in the msg, in order to display error msg,
			// Which fits in error message area of the wizard. 
			int i = msg.indexOf("IUPL0101E"); //$NON-NLS-1$
			if(i>=0){
				msg = AuthoringUIResources.bind(AuthoringUIResources.duplicatePluginNameError_msg, getPluginName()); //$NON-NLS-1$
			}
			setErrorMessage(msg);
			setMessage(null);
		}

		return answer;
	}

	/**
	 * @see org.eclipse.jface.wizard.WizardPage#isPageComplete()
	 */
	public boolean isPageComplete() {
		return isTextNonEmpty(nameText) && getErrorMessage() == null;
	}

	/**
	 * Returns true if the given Text control contains a vlaid text.
	 */
	private static boolean isTextNonEmpty(Text t) {
		String text = t.getText();
		return text != null && text.trim().length() > 0;
	}

	/**
	 * Returns the name for the plug-in.
	 */
	public String getPluginName() {
		return nameText.getText() != null ? nameText.getText().trim() : null;
	}

	/**
	 * Returns the brief description.
	 */
	public String getBriefDescription() {
		return briefDescText.getText();
	}

	/**
	 * Returns the authors.
	 */
	public String getAuthors() {
		return authorsText.getText();
	}

	/**
	 * Returns the referenced plug-ins.
	 */
	public Object[] getReferencedPlugins() {
		return referencedPluginsViewer.getCheckedElements();
	}

}
