/*
 * Copyright 2006 Maskat Project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.maskat.ide.action;

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.framework.BasicDef;
import org.maskat.framework.IBasicDef;
import org.maskat.framework.screendef.DivSplitDef;
import org.maskat.framework.screendef.LayoutDef;
import org.maskat.ide.MaskatIDEPlugin;
import org.maskat.ide.gef.editparts.SplitEditPart;
import org.maskat.ide.gef.editparts.SplitPageEditPart;
import org.maskat.ide.gef.models.SplitModel;
import org.maskat.ide.gef.models.TabDef;

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 = this.getSelectedObjects();
		if (objects.isEmpty())
			return false;
		if (objects.size() == 1) {
			if (objects.get(0) instanceof EditPart) {
				Object model = ((EditPart) objects.get(0)).getModel();
				if (model instanceof LayoutDef) {
					return false;
				}
				if (model instanceof SplitModel || model instanceof DivSplitDef)
					return false;
			}
		} else {
			for (int i = 0; i < objects.size(); i++) {
				if (!(objects.get(i) instanceof EditPart)) {
					return false;
				}
				if (objects.get(i) instanceof SplitEditPart
						|| objects.get(i) instanceof SplitPageEditPart)
					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) {
					return false;// make sure they are from the same parent
				}
				if (objects.contains(parent2)) {
					return false;
					// make sure the objects selected have no
					// parent-child relationship
				}
			}
			return true;
		}
		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 temp = (Object) copyTarget.get(i);
			BasicDef def = null;
			if (temp instanceof TabDef) {
				def = ((TabDef) temp).getTabItemDef();
				if (copyTarget.contains(def))
					continue;// tabとtabItem両方一緒にコピーされる時、tabItemしか処理しない
			} else {
				def = (BasicDef) temp;
			}
			if (isAnscestorContained(copyTarget, def))
				continue;
			else
				try {
					result.add(def.clone());
				} catch (CloneNotSupportedException e) {
					// should not happen
					MessageDialog.openError(this.getWorkbenchPart().getSite().getShell(),
							"コピー操作失敗", "貼り付け操作に失敗しました。詳しくはエラーログを参照してください。");
					// エラーログ
					MaskatIDEPlugin.getDefault().getLog().log(
							new Status(IStatus.ERROR, MaskatIDEPlugin.PLUGIN_ID,
									IStatus.ERROR, e.getMessage(), e));
				}
		}

		Clipboard.getDefault().setContents(result);
	}

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