/*******************************************************************************
 * Copyright (c) 2005, 2007 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.pde.internal.ui.editor.target;

import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.core.plugin.TargetPlatform;
import org.eclipse.pde.internal.core.itarget.*;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.editor.*;
import org.eclipse.pde.internal.ui.elements.DefaultTableProvider;
import org.eclipse.pde.internal.ui.parts.TablePart;
import org.eclipse.pde.internal.ui.util.SWTUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

public class LocationsSection extends TableSection {

	private TableViewer fContentViewer;

	class ContentProvider extends DefaultTableProvider {
		public Object[] getElements(Object parent) {
			ITarget target = getTarget();
			return target.getAdditionalDirectories();
		}
	}

	public LocationsSection(PDEFormPage page, Composite parent) {
		super(page, parent, Section.DESCRIPTION, new String[] {PDEUIMessages.LocationsSection_add, PDEUIMessages.LocationsSection_edit, PDEUIMessages.LocationsSection_remove});
	}

	protected void createClient(Section section, FormToolkit toolkit) {
		section.setLayout(FormLayoutFactory.createClearTableWrapLayout(false, 1));
		Composite client = toolkit.createComposite(section);
		client.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2));
		client.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL));

		createViewerPartControl(client, SWT.MULTI, 2, toolkit);

		TablePart tablePart = getTablePart();
		GridData data = (GridData) tablePart.getControl().getLayoutData();
		data.grabExcessVerticalSpace = true;
		data.grabExcessHorizontalSpace = true;
		fContentViewer = tablePart.getTableViewer();
		fContentViewer.setContentProvider(new ContentProvider());
		fContentViewer.setLabelProvider(PDEPlugin.getDefault().getLabelProvider());
		fContentViewer.setInput(getTarget());
		fContentViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				updateButtons();
			}
		});
		fContentViewer.setComparator(new ViewerComparator() {
			public int compare(Viewer viewer, Object e1, Object e2) {
				IAdditionalLocation loc1 = (IAdditionalLocation) e1;
				return loc1.getPath().compareToIgnoreCase(((IAdditionalLocation) e2).getPath());
			}
		});
		fContentViewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				// if user double clicked on one selected item
				if (((StructuredSelection) fContentViewer.getSelection()).toArray().length == 1)
					handleEdit();
			}
		});

		toolkit.paintBordersFor(client);
		section.setClient(client);
		section.setText(PDEUIMessages.LocationsSection_title);
		section.setDescription(PDEUIMessages.LocationsSection_description);
		GridData sectionData = new GridData(GridData.FILL_BOTH);
		sectionData.horizontalSpan = 2;
		section.setLayoutData(sectionData);
		updateButtons();

		getModel().addModelChangedListener(this);
	}

	private ITarget getTarget() {
		return getModel().getTarget();
	}

	private ITargetModel getModel() {
		return (ITargetModel) getPage().getPDEEditor().getAggregateModel();
	}

	protected void updateButtons() {
		int selectionNum = ((StructuredSelection) fContentViewer.getSelection()).toArray().length;
		TablePart table = getTablePart();
		table.setButtonEnabled(1, selectionNum == 1);
		table.setButtonEnabled(2, selectionNum > 0);
	}

	protected void buttonSelected(int index) {
		switch (index) {
			case 0 :
				handleAdd();
				break;
			case 1 :
				handleEdit();
				break;
			case 2 :
				handleDelete();
		}
	}

	protected void handleAdd() {
		showDialog(null);
	}

	protected void handleEdit() {
		showDialog((IAdditionalLocation) ((StructuredSelection) fContentViewer.getSelection()).iterator().next());
	}

	protected void handleDelete() {
		IStructuredSelection ssel = (IStructuredSelection) fContentViewer.getSelection();
		if (ssel.size() > 0) {
			Object[] objects = ssel.toArray();
			ITarget target = getTarget();
			IAdditionalLocation[] dirs = new IAdditionalLocation[objects.length];
			System.arraycopy(objects, 0, dirs, 0, objects.length);
			target.removeAdditionalDirectories(dirs);
		}
	}

	private void showDialog(final IAdditionalLocation location) {
		final ITarget model = getTarget();
		BusyIndicator.showWhile(fContentViewer.getTable().getDisplay(), new Runnable() {
			public void run() {
				LocationDialog dialog = new LocationDialog(fContentViewer.getTable().getShell(), model, location);
				dialog.create();
				SWTUtil.setDialogSize(dialog, 500, -1);
				dialog.open();
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.pde.internal.ui.editor.PDESection#modelChanged(org.eclipse.pde.core.IModelChangedEvent)
	 */
	public void modelChanged(IModelChangedEvent e) {
		if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
			handleModelEventWorldChanged(e);
			return;
		}
		Object[] objects = e.getChangedObjects();
		if (e.getChangeType() == IModelChangedEvent.INSERT) {
			for (int i = 0; i < objects.length; i++) {
				if (objects[i] instanceof IAdditionalLocation) {
					fContentViewer.add(objects[i]);
				}
			}
		} else if (e.getChangeType() == IModelChangedEvent.REMOVE) {
			for (int i = 0; i < objects.length; i++) {
				if (objects[i] instanceof IAdditionalLocation) {
					fContentViewer.remove(objects[i]);
				}
			}
		}
		if (e.getChangedProperty() == IAdditionalLocation.P_PATH) {
			fContentViewer.refresh();
		}
	}

	/**
	 * @param event
	 */
	private void handleModelEventWorldChanged(IModelChangedEvent event) {
		// Reload input
		fContentViewer.setInput(getTarget());
		// Perform the refresh
		refresh();
	}

	public boolean doGlobalAction(String actionId) {
		if (actionId.equals(ActionFactory.DELETE.getId())) {
			handleDelete();
			return true;
		}
		if (actionId.equals(ActionFactory.CUT.getId())) {
			handleDelete();
			return false;
		}
		if (actionId.equals(ActionFactory.PASTE.getId())) {
			doPaste();
			return true;
		}
		return false;
	}

	protected boolean canPaste(Object target, Object[] objects) {
		for (int i = 0; i < objects.length; i++) {
			if (objects[i] instanceof IAdditionalLocation)
				return true;
		}
		return false;
	}

	protected void doPaste(Object target, Object[] objects) {
		for (int i = 0; i < objects.length; i++) {
			if (objects[i] instanceof IAdditionalLocation && !hasPath(((IAdditionalLocation) objects[i]).getPath())) {
				IAdditionalLocation loc = (IAdditionalLocation) objects[i];
				loc.setModel(getModel());
				getTarget().addAdditionalDirectories(new IAdditionalLocation[] {loc});
			}
		}
	}

	protected boolean hasPath(String path) {
		Path checkPath = new Path(path);
		IAdditionalLocation[] locs = getModel().getTarget().getAdditionalDirectories();
		for (int i = 0; i < locs.length; i++) {
			if (new Path(locs[i].getPath()).equals(checkPath))
				return true;
		}
		return isTargetLocation(checkPath);
	}

	private boolean isTargetLocation(Path path) {
		ILocationInfo info = getModel().getTarget().getLocationInfo();
		if (info.useDefault()) {
			Path home = new Path(TargetPlatform.getDefaultLocation());
			return home.equals(path);
		}
		return new Path(info.getPath()).equals(path);
	}

	public void dispose() {
		ITargetModel model = getModel();
		if (model != null)
			model.removeModelChangedListener(this);
		super.dispose();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.forms.AbstractFormPart#refresh()
	 */
	public void refresh() {
		fContentViewer.refresh();
		updateButtons();
		super.refresh();
	}

	protected void fillContextMenu(IMenuManager manager) {
		IStructuredSelection ssel = (IStructuredSelection) fContentViewer.getSelection();
		if (ssel == null)
			return;

		Action removeAction = new Action(PDEUIMessages.ContentSection_remove) {
			public void run() {
				handleDelete();
			}
		};
		removeAction.setEnabled(isEditable() && ssel.size() > 0);
		manager.add(removeAction);

		manager.add(new Separator());

		getPage().getPDEEditor().getContributor().contextMenuAboutToShow(manager);
	}

	protected void selectionChanged(IStructuredSelection selection) {
		getPage().getPDEEditor().setSelection(selection);
	}
}
