//------------------------------------------------------------------------------
// 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.dialogs;

import java.util.ArrayList;

import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.AuthoringUIText;
import org.eclipse.epf.authoring.ui.providers.VariabilityElementLabelProvider;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.command.MoveInCategoryCommand;
import org.eclipse.epf.library.edit.util.ContentElementOrderList;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;

/**
 * Open an dialog to order content elements
 * 
 * @author Shashidhar Kannoori
 * @since 1.0
 *
 */
public class ContentElementsOrderDialog extends Dialog {

	private Composite baseComposite;

	private Button ctrl_up, ctrl_down;

	private Table ctrl_steps;

	private TableViewer stepsTableViewer;

	private ContentElementOrderList allSteps;

	private IStructuredContentProvider stepsViewerContentProvider;

	private ILabelProvider stepsViewerLabelProvider;

	// private Task contentElement;
	private ContentElement contentElement;

	private IActionManager actionManager;

	private ArrayList commands = new ArrayList();

	/**
	 * Creates a <code>AdvancedSearchDialog</code> giveb the parent control.
	 * 
	 * @param parent
	 *            The parent control.
	 */
	public ContentElementsOrderDialog(Shell parent,
			ContentElement contentElement, IActionManager actionManager) {
		super(parent);
		this.contentElement = contentElement;
		this.actionManager = actionManager;
		allSteps = null;
	}

	/**
	 * @see Dialog#createDialogArea(Composite parent)
	 */
	protected Control createDialogArea(Composite parent) {
		baseComposite = (Composite) super.createDialogArea(parent);
		final GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 4;
		baseComposite.setLayout(gridLayout);
		baseComposite.setLayoutData(new GridData());

		// Empty line
		createLabel(baseComposite, " ", 4); //$NON-NLS-1$

		createLabel(baseComposite, " ", 1); //$NON-NLS-1$
		createLabel(
				baseComposite,
				AuthoringUIResources.ContentElementsOrderDialog_ContentElement_text, 3); //$NON-NLS-1$

		createLabel(baseComposite, " ", 1); //$NON-NLS-1$
		ctrl_steps = new Table(baseComposite, SWT.MULTI | SWT.BORDER);
		{
			GridData gridData = new GridData(GridData.FILL_BOTH);
			gridData.horizontalSpan = 2;
			gridData.widthHint = 300;
			gridData.heightHint = 400;
			ctrl_steps.setLayoutData(gridData);
		}

		initProviders();

		stepsTableViewer = new TableViewer(ctrl_steps);
		stepsTableViewer.setContentProvider(stepsViewerContentProvider);
		stepsTableViewer.setLabelProvider(stepsViewerLabelProvider);

		Composite orderButtonPane = new Composite(baseComposite, SWT.NULL);
		{
			GridData gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER
					| GridData.HORIZONTAL_ALIGN_CENTER);
			gridData.horizontalSpan = 1;
			orderButtonPane.setLayoutData(gridData);
			orderButtonPane.setLayout(new GridLayout());
		}

		ctrl_up = createButton(orderButtonPane, AuthoringUIText.UP_BUTTON_TEXT);
		ctrl_up.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		ctrl_down = createButton(orderButtonPane,
				AuthoringUIText.DOWN_BUTTON_TEXT);
		ctrl_down.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		ctrl_up.setEnabled(false);
		ctrl_down.setEnabled(false);
		// Empty line
		createLabel(baseComposite, " ", 4); //$NON-NLS-1$

		createLine(baseComposite, 4);

		super
				.getShell()
				.setText(
						AuthoringUIResources.ContentElementsOrderDialog_description_text); //$NON-NLS-1$

		addListeners();
		loadData();

		return baseComposite;
	}

	private void createLine(Composite parent, int ncol) {
		Label line = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL
				| SWT.BOLD);
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.horizontalSpan = ncol;
		line.setLayoutData(gridData);
	}

	private Label createLabel(Composite parent, String text, int nCol) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		{
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			gridData.horizontalSpan = nCol;
			label.setLayoutData(gridData);
		}

		return label;
	}

	private Button createButton(Composite parent, String label) {
		Button button = new Button(parent, SWT.NONE);
		button.setText(label);
		return button;
	}

	/**
	 * Creates the dialog buttons.
	 */
	protected void createButtonsForButtonBar(Composite parent) {
		// Create the OK button.
		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
				true);

		// Create the Cancel button.
		createButton(parent, IDialogConstants.CANCEL_ID,
				IDialogConstants.CANCEL_LABEL, false);
	}

	private void initProviders() {
		stepsViewerContentProvider = new AdapterFactoryContentProvider(
				TngAdapterFactory.INSTANCE
						.getNavigatorView_ComposedAdapterFactory()) {
			public Object[] getElements(Object object) {
				if (allSteps == null) {
					allSteps = new ContentElementOrderList(
							contentElement,
							ContentElementOrderList.CONTENT_ELEMENTS__FOR_ELEMENT_AND_PARENTS);
				}
				return allSteps.toArray();
			}
		};

		stepsViewerLabelProvider = new VariabilityElementLabelProvider(
				TngAdapterFactory.INSTANCE
						.getNavigatorView_ComposedAdapterFactory()) {

			public boolean isExternal(Object element) {
				return !((CustomCategory) contentElement)
						.getCategorizedElements().contains(element);
			}

		};
	}

	public void addListeners() {

		stepsTableViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {

					public void selectionChanged(SelectionChangedEvent event) {
						IStructuredSelection selection = (IStructuredSelection) stepsTableViewer
								.getSelection();
						if (selection.size() > 0
								&& !TngUtil.isLocked(contentElement)) {
							if (stepsTableViewer.getTable().getSelectionIndex() > 0
									&& !TngUtil.isLocked(contentElement)
									&& selection.size() == 1) {
								ctrl_up.setEnabled(true);
							} else
								ctrl_up.setEnabled(false);

							if (stepsTableViewer.getTable().getSelectionIndex() < stepsTableViewer
									.getTable().getItemCount() - 1
									&& !TngUtil.isLocked(contentElement)
									&& selection.size() == 1) {
								ctrl_down.setEnabled(true);
							} else
								ctrl_down.setEnabled(false);
						}
					}

				});

		ctrl_up.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) stepsTableViewer
						.getSelection();

				ArrayList moveUpItems = new ArrayList();
				moveUpItems.addAll(selection.toList());
				EStructuralFeature feature = UmaPackage.eINSTANCE
						.getCustomCategory_CategorizedElements();
				MoveInCategoryCommand cmd = new MoveInCategoryCommand(
						(CustomCategory) contentElement, moveUpItems, allSteps,
						feature, ModelStructure.DEFAULT.customCategoryPath, 1);
				actionManager.execute(cmd);
				commands.add(cmd);

				stepsTableViewer.refresh();

				if (stepsTableViewer.getTable().getSelectionIndex() > 0
						&& !TngUtil.isLocked(contentElement)) {
					ctrl_up.setEnabled(true);
				} else
					ctrl_up.setEnabled(false);
				if (stepsTableViewer.getTable().getSelectionIndex() < stepsTableViewer
						.getTable().getItemCount() - 1
						&& !TngUtil.isLocked(contentElement)) {
					ctrl_down.setEnabled(true);
				} else
					ctrl_down.setEnabled(false);
			}
		});

		ctrl_down.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) stepsTableViewer
						.getSelection();
				ArrayList moveDownItems = new ArrayList();
				moveDownItems.addAll(selection.toList());
				EStructuralFeature feature = UmaPackage.eINSTANCE
						.getCustomCategory_CategorizedElements();
				MoveInCategoryCommand cmd = new MoveInCategoryCommand(
						(CustomCategory) contentElement, moveDownItems, allSteps,
						feature, ModelStructure.DEFAULT.customCategoryPath,	0);
				actionManager.execute(cmd);
				commands.add(cmd);

				stepsTableViewer.refresh();

				if (stepsTableViewer.getTable().getSelectionIndex() > 0
						&& !TngUtil.isLocked(contentElement)) {
					ctrl_up.setEnabled(true);
				} else
					ctrl_up.setEnabled(false);
				if (stepsTableViewer.getTable().getSelectionIndex() < stepsTableViewer
						.getTable().getItemCount() - 1
						&& !TngUtil.isLocked(contentElement)) {
					ctrl_down.setEnabled(true);
				} else
					ctrl_down.setEnabled(false);
			}
		});
	}

	/**
	 * Load initial data from model
	 */
	private void loadData() {
		stepsTableViewer.setInput(contentElement);
	}

	/**
	 * Called when the OK button is selected.
	 */
	protected void okPressed() {
		allSteps.apply();
		super.okPressed();
	}

	protected void cancelPressed() {
		if (!commands.isEmpty()) {
			for (int i = commands.size() - 1; i > -1; i--) {
				Object cmd = commands.get(i);
				if (cmd instanceof MoveInCategoryCommand) {
					((MoveInCategoryCommand) cmd).undo();
				}
			}
		}
		super.cancelPressed();
	}

}