/**
 * File:    SelectNameWizardPage.java
 * Created: 06.12.2006
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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:
 *    Christian Seitz, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.misc.wizards.model;

import java.io.File;
import java.util.Collections;

import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.CreateChildCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jwt.meta.model.core.CoreFactory;
import org.eclipse.jwt.meta.model.core.CorePackage;
import org.eclipse.jwt.we.Plugin;
import org.eclipse.jwt.we.PluginProperties;
import org.eclipse.jwt.we.misc.util.GeneralHelper;
import org.eclipse.jwt.we.misc.wizards.PackageFilter;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.jwt.meta.model.core.Package;


/**
 * WizardPage to specify name and Package of a new Application, Role, Data
 * 
 * @author Christian Seitz (chr.seitz@gmx.de), Programming distributed Systems Lab,
 *         University of Augsburg, Germany, www.ds-lab.org.
 */
public class SelectNameWizardPage
		extends WizardPage
{

	/**
	 * The TextField for the Name
	 */
	protected Text nameField;

	/**
	 * The TextField for the path of the Icon
	 */
	protected Text iconField;

	/**
	 * The Tree for the package selection
	 */
	protected Tree packageTree;

	/**
	 * The context menu for the package selection
	 */
	protected Menu contextMenu;

	protected MenuItem addSubpackage;

	/**
	 * The composite
	 */
	protected Composite composite;

	/**
	 * This SelectNameWizardPage
	 */
	protected SelectNameWizardPage thispage;

	/**
	 * The default package.
	 */
	protected Package defaultPackage = null;


	/**
	 * Create a new wizard page instance.
	 * 
	 * @param pageId
	 *            The pageId
	 * @param workbench
	 *            The current workbench
	 */
	public SelectNameWizardPage(String pageId, IWorkbench workbench)
	{
		this(pageId, null, workbench);
	}


	/**
	 * Create a new wizard page instance.
	 * 
	 * @param pageId
	 *            The pageId
	 * @param defaultPackage
	 *            The default package
	 * @param workbench
	 *            The current workbench
	 */
	public SelectNameWizardPage(String pageId,
			org.eclipse.jwt.meta.model.core.Package defaultPackage, IWorkbench workbench)
	{
		super(pageId);
		thispage = this;
		this.defaultPackage = defaultPackage;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite
	 * )
	 */
	public void createControl(Composite parent)
	{
		composite = new Composite(parent, SWT.NONE);
		final Shell shell = composite.getShell();
		{
			GridLayout layout = new GridLayout();
			layout.numColumns = 3;
			composite.setLayout(layout);
			GridData data = new GridData();
			data.verticalAlignment = GridData.FILL;
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessVerticalSpace = true;
			composite.setLayoutData(data);
		}

		// Package Selection
		packageTree = new Tree(composite, SWT.SINGLE);
		{
			GridData data = new GridData();
			data.grabExcessHorizontalSpace = true;
			data.grabExcessVerticalSpace = true;
			data.horizontalAlignment = GridData.FILL;
			data.verticalAlignment = GridData.FILL;
			data.horizontalSpan = 3;
			packageTree.setLayoutData(data);
		}
		final TreeViewer packageViewer = new TreeViewer(packageTree);
		packageViewer.setContentProvider(new AdapterFactoryContentProvider(
				getAdapterFactory()));
		packageViewer.setLabelProvider(new AdapterFactoryLabelProvider(
				getAdapterFactory()));
		packageViewer.setInput(GeneralHelper.getActiveInstance().getMainModelResource());
		PackageFilter filter = new PackageFilter();
		packageViewer.addFilter(filter);
		// avoids displaying of unnecessary "+" symbols in the tree
		packageViewer.expandAll();

		packageTree.addSelectionListener(selListener);

		contextMenu = new Menu(composite.getShell(), SWT.POP_UP);
		packageTree.setMenu(contextMenu);

		addSubpackage = new MenuItem(contextMenu, SWT.PUSH);
		addSubpackage.setText(PluginProperties.wizards_NewPackage);

		// add package button
		final Button addPackageButton = new Button(composite, SWT.FLAT);
		addPackageButton.setEnabled(false);
		addPackageButton.setText(PluginProperties.wizards_NewPackage);
		{
			GridData data = new GridData();
			data.horizontalSpan = 3;
			data.verticalSpan = 1;
			data.horizontalAlignment = GridData.END;
			addPackageButton.setLayoutData(data);
		}
		addPackageButton.addSelectionListener(new SelectionAdapter()
		{

			@Override
			public void widgetSelected(SelectionEvent event)
			{
				CreatePackageDialog packagedialog = new CreatePackageDialog(shell);
				packagedialog.open(thispage);
			}
		});

		// selection listener for tree
		packageTree.addSelectionListener(new SelectionAdapter()
		{

			@Override
			public void widgetSelected(SelectionEvent event)
			{
				if (packageTree.getSelection()[0].getData() instanceof org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl)
				{
					addSubpackage.setEnabled(false);
					addPackageButton.setEnabled(false);
				}
				else
				{
					addSubpackage.setEnabled(true);
					addPackageButton.setEnabled(true);
				}
			}
		});

		addSubpackage.addSelectionListener(new SelectionAdapter()
		{

			@Override
			public void widgetSelected(SelectionEvent event)
			{
				CreatePackageDialog packagedialog = new CreatePackageDialog(shell);
				packagedialog.open(thispage);
			}
		});

		// Name Selection
		Label nameLabel = new Label(composite, SWT.RIGHT);
		nameLabel
				.setText(org.eclipse.jwt.meta.PluginProperties.model_NamedElement_name_name
						+ ":"); //$NON-NLS-1$
		nameField = new Text(composite, SWT.BORDER);
		{
			GridData data = new GridData();
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessHorizontalSpace = true;
			data.horizontalSpan = 2;
			nameField.setLayoutData(data);
		}
		nameField.addModifyListener(validator);

		// Icon Selection
		Label iconLabel = new Label(composite, SWT.RIGHT);
		iconLabel
				.setText(org.eclipse.jwt.meta.PluginProperties.model_NamedElement_icon_name
						+ ":"); //$NON-NLS-1$
		iconField = new Text(composite, SWT.BORDER);
		{
			GridData data = new GridData();
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessHorizontalSpace = true;
			iconField.setLayoutData(data);
		}
		iconField.addModifyListener(validator);
		Button browseButton = new Button(composite, SWT.PUSH);
		browseButton.setText(PluginProperties.browse_button);
		browseButton.addSelectionListener(new SelectionAdapter()
		{

			@Override
			public void widgetSelected(SelectionEvent event)
			{
				String filePath = ""; //$NON-NLS-1$
				String result = ""; //$NON-NLS-1$
				String[] filterExtensions =
				{ "*.png;*.gif;*.ico" }; //$NON-NLS-1$
				String[] extensionNames =
				{ PluginProperties.wizards_Files_iconfiles };
				FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
				fileDialog.setFilterExtensions(filterExtensions);
				fileDialog.setFilterNames(extensionNames);

				// if old path was empty, use default icon path (<base>\icons)
				if (iconField.getText().equals("")) //$NON-NLS-1$
				{
					File iconPath = new File("icons"); //$NON-NLS-1$
					if (iconPath.exists())
					{
						fileDialog.setFilterPath(iconPath.getAbsolutePath());
					}
				}

				filePath = fileDialog.open();
				/*
				 * if (fileDialog.getFileName() != null &&
				 * fileDialog.getFileName().length() > 0) { filePath =
				 * fileDialog.getFilterPath() + File.separator + fileDialog.getFileName();
				 * }
				 */
				// iconField.setText(filePath);
				if (filePath != null)
				{
					Path iconPath = new Path(filePath);
					// icon-path within the plugin ?
					String temp = ""; //$NON-NLS-1$
					for (int i = iconPath.segmentCount() - 1; i > 0; i--)
					{
						if (temp != "") //$NON-NLS-1$
							temp = iconPath.segment(i) + "/" + temp; //$NON-NLS-1$
						else
							temp = iconPath.segment(i) + temp;

						if (pathinPlugin(temp))
							result = temp;
					}

					// if path not relative, return absolute path from dialog
					if (result == "") //$NON-NLS-1$
						result = filePath;

					iconField.setText(result);
				}
			}
		});

		// if there is a default package, select it
		if (defaultPackage != null)
		{
			packageTree.setSelection((TreeItem) packageViewer
					.testFindItem(defaultPackage));
			addPackageButton.setEnabled(true);
		}

		// select name field
		nameField.setFocus();

		// finish
		setPageComplete(validatePage());
		setControl(composite);
	}


	/**
	 * @return The Name
	 */
	@Override
	public String getName()
	{
		return nameField.getText();
	}


	/**
	 * 
	 * @return The selected Package
	 */
	public Package getPackage()
	{
		if (packageTree.getSelection() != null)
		{
			if (packageTree.getSelection()[0].getData() instanceof org.eclipse.jwt.meta.model.core.Package)
			{
				return (Package) packageTree.getSelection()[0].getData();
			}
		}
		return null;
	}


	/**
	 * 
	 * @return The Path of the selected Icon
	 */
	public String getIconPath()
	{
		return iconField.getText();
	}


	/**
	 * Next Button is only available if Name and Package are set
	 */
	protected boolean validatePage()
	{

		if (nameField.getText().length() == 0)
		{
			setErrorMessage(null);
			return false;
		}
		// if (packageTree.getSelection() != null) {
		if (packageTree.getSelection().length != 0)
		{

			if (packageTree.getSelection()[0].getData() instanceof org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl)
			{
				setErrorMessage(null);
				return false;

			}

			return true;
		}

		return false;
	}


	/**
	 * @return The EMF EditingDomain.
	 */
	public EditingDomain getEditingDomain()
	{
		return (EditingDomain) GeneralHelper.getActiveInstance().getAdapter(
				EditingDomain.class);
	}


	/**
	 * @return The {@link AdapterFactory} from an {@link AdapterFactoryEditingDomain} if
	 *         available.
	 */
	public AdapterFactory getAdapterFactory()
	{
		return (AdapterFactory) GeneralHelper.getActiveInstance().getAdapter(
				AdapterFactory.class);
	}

	/**
	 * 
	 */
	protected ModifyListener validator = new ModifyListener()
	{

		public void modifyText(ModifyEvent e)
		{
			setPageComplete(validatePage());
		}
	};

	/**
	 * 
	 */
	protected SelectionListener selListener = new SelectionListener()
	{

		public void widgetSelected(SelectionEvent e)
		{
			setPageComplete(validatePage());
		}


		public void widgetDefaultSelected(SelectionEvent e)
		{

		}
	};


	/**
	 * Checks if the file/path lies within the plugin
	 * 
	 * @param path
	 *            The file-path.
	 * @return <code>true</code>, if path lies within plugin. <code>false</code> if path
	 *         does not lie within plugin.
	 */
	private boolean pathinPlugin(String path)
	{
		// look for the image (this will check both the plugin and fragment
		// folders
		ImageDescriptor result = AbstractUIPlugin.imageDescriptorFromPlugin(Plugin
				.getId(), path);

		if (result == null)
		{
			return false;
		}

		return true;
	}


	/**
	 * Creates a new subpackage
	 * 
	 * @param superpackage
	 *            The superpackage
	 * @param packagename
	 *            The name of the new package
	 */
	public void createSubpackage(String packagename)
	{
		Package superpackage;

		if (packageTree.getSelection() != null)
		{
			if (packageTree.getSelection()[0].getData() instanceof org.eclipse.jwt.meta.model.core.Package)
			{
				superpackage = (Package) packageTree.getSelection()[0].getData();
			}
			else
				superpackage = null;
		}
		else
			superpackage = null;

		CoreFactory factory = CoreFactory.eINSTANCE;
		Package newpackage = factory.createPackage();
		newpackage.setName(packagename);
		newpackage.setSuperpackage(superpackage);

		// This command creates the new Package
		CommandParameter childDescriptor = new CommandParameter(null,
				CorePackage.Literals.PACKAGE__ELEMENTS, newpackage);
		Command cmd = CreateChildCommand.create(getEditingDomain(), superpackage,
				childDescriptor, Collections.singleton(superpackage));

		getEditingDomain().getCommandStack().execute(cmd);
	}

}
