/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * 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:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.ui.editors.layout.actions;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.internal.GEFMessages;
import org.eclipse.gef.ui.actions.Clipboard;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;

import org.maskat.core.MaskatElement;
import org.maskat.core.layout.LayoutElement;
import org.maskat.ui.MaskatUIPlugin;
import org.maskat.ui.Messages;
import org.maskat.ui.editors.layout.editparts.ComboItemEditPart;
import org.maskat.ui.editors.layout.editparts.DivSplitEditPart;
import org.maskat.ui.editors.layout.editparts.GridHeaderEditPart;
import org.maskat.ui.editors.layout.editparts.LayoutEditPart;
import org.maskat.ui.editors.layout.editparts.SplitEditPart;
import org.maskat.ui.editors.layout.editparts.WindowEditPart;
import org.maskat.ui.editors.layout.models.ModelWrapper;

public class CopyComponentAction extends SelectionAction {

	public CopyComponentAction(IWorkbenchPart part) {
		super(part);
		setId(ActionFactory.COPY.getId());
		setText(GEFMessages.CopyAction_Label);
		setToolTipText(GEFMessages.CopyAction_Tooltip);
		ISharedImages sharedImages = PlatformUI.getWorkbench()
				.getSharedImages();
		setImageDescriptor(sharedImages.getImageDescriptor(
				ISharedImages.IMG_TOOL_COPY));
		setDisabledImageDescriptor(sharedImages.getImageDescriptor(
				ISharedImages.IMG_TOOL_COPY_DISABLED));
	}

	protected boolean calculateEnabled() {
		List objects = getSelectedObjects();
		if (objects.isEmpty()) {
			return false;
		}
		for (int i = 0; i < objects.size(); i++) {
			EditPart part = (EditPart) objects.get(i);
			if (!(part instanceof EditPart)) {
				return false;
			}
			if (part instanceof LayoutEditPart || part instanceof SplitEditPart ||
				part instanceof DivSplitEditPart || part instanceof WindowEditPart) {
				return false;
			}
			if (objects.size() == 1 && i == 0) {
				if (part instanceof ComboItemEditPart ||
					part instanceof GridHeaderEditPart) {
					return false;
				}
			}
		}
		EditPart parent = ((EditPart) objects.get(0)).getParent();
		for (int i = 1; i < objects.size(); i++) {
			EditPart parent2 = ((EditPart) objects.get(i)).getParent();
			if (parent2 != parent) {
				// make sure they are from the same parent
				return false;
			}
			if (objects.contains(parent2)) {
				return false;
				// make sure the objects selected have no
				// parent-child relationship
			}
		}		
		return true;
	}

	public void run() {
		List editparts = getSelectedObjects();
		
		// clone the basicdefs and set them into the clipboard
		List copyTarget = new ArrayList();
		for (int i = 0; i < editparts.size(); i++) {
			EditPart agep = (EditPart) editparts.get(i);
			Object model = agep.getModel();
			copyTarget.add(model);
		}
		// filter into list without dependent.
		List result = new ArrayList();
		for (int i = 0; i < copyTarget.size(); i++) {
			Object model = copyTarget.get(i);
			if (model instanceof ModelWrapper) {
				model = ((ModelWrapper) model).getModel();
			}
			if (result.contains(model)) {
				continue;
			}
			LayoutElement def = (LayoutElement) model;
			if (isAnscestorContained(copyTarget, def)) {
				continue;
				
			} else {
				try {
					result.add(def.clone());
				} catch (CloneNotSupportedException e) {
					MessageDialog.openError(this.getWorkbenchPart().getSite().getShell(),
							Messages.getString("layout.cmd.msg.error.title"), //$NON-NLS-1$
							Messages.getString("layout.cmd.copy.msg.error")); //$NON-NLS-1$
					MaskatUIPlugin.log(new Status(IStatus.ERROR,
							MaskatUIPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
				}
			}
		}
		Clipboard.getDefault().setContents(result);
	}

	private boolean isAnscestorContained(List list, MaskatElement def) {
		if (def == null || list == null) {
			return false;
		}
		MaskatElement parentDef = def.getParent();
		while (parentDef != null) {
			if (list.contains(parentDef)) {
				return true;
			}
			parentDef = parentDef.getParent();
		}
		return false;
	}
}
