/**
 * File:    ImportLayoutDataCommand.java
 * Created: 28.12.2008
 *
 *
/*******************************************************************************
 * 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 Saad, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.commands.view;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.commands.Command;
import org.eclipse.jwt.meta.model.core.GraphicalElement;
import org.eclipse.jwt.meta.model.processes.Scope;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.jwt.we.misc.util.EMFHelper;
import org.eclipse.jwt.we.misc.views.LayoutDataManager;
import org.eclipse.jwt.we.misc.views.Views;
import org.eclipse.jwt.we.model.view.LayoutData;
import org.eclipse.jwt.we.model.view.impl.ViewFactoryImpl;

/**
 * A command to import layout data from a source view to a target view.
 * 
 * @version $Id: ImportLayoutDataCommand.java,v 1.2 2009/11/04 17:18:38 chsaad
 *          Exp $
 * @author Christian Saad, Programming distributed Systems Lab, University of
 *         Augsburg, Germany, www.ds-lab.org
 */
public class ImportLayoutDataCommand extends Command
{

	/**
	 * A Logger.
	 */
	@SuppressWarnings("unused")
	private static final Logger logger = Logger.getLogger(ImportLayoutDataCommand.class);

	/**
	 * The workflow editor.
	 */
	private WEEditor weeditor;

	/**
	 * The table to store copies of the original layoutdata and the target
	 * layout data.
	 */
	private HashMap layoutData;

	/**
	 * Import layoutdata only for new elements?
	 */
	private boolean onlyNew;

	/**
	 * The view id of the source view.
	 */
	private String src_viewID;

	/**
	 * The view id of the target view.
	 */
	private String dest_viewID;

	/**
	 * The selected scopes.
	 */
	private Set<Scope> selectedScopes;


	/**
	 * Creates a new command for changing constraints of a element.
	 * 
	 * @param src_viewID
	 * @param dest_viewID
	 * @param onlyNew
	 */
	public ImportLayoutDataCommand(WEEditor weeditor, Set<Scope> selectedScopes,
			String src_viewID, String dest_viewID, boolean onlyNew)
	{
		this.src_viewID = src_viewID;
		this.dest_viewID = dest_viewID;
		this.onlyNew = onlyNew;
		this.selectedScopes = selectedScopes;
		this.weeditor = weeditor;
	}


	/**
	 * Store layout data of new source and the original data in hashtable to be
	 * switched later on.
	 * 
	 * @param scope
	 */
	private void layoutScope(Scope scope)
	{
		Set contents = new HashSet();
		contents.add(scope);
		contents.addAll(scope.eContents());
		contents.addAll(EMFHelper.getAllContainedReferences(weeditor, contents));
		contents.addAll(EMFHelper.getAllContainedReferenceEdges(weeditor, contents));
		contents.remove(scope);

		// create the table with copies of source layoutdata and corresponding
		// target
		// layout data
		for (Iterator iter = contents.iterator(); iter.hasNext();)
		{
			EObject eobject = (EObject) iter.next();

			// for all graphical elements that are visible in the current view
			if (eobject instanceof GraphicalElement
					&& Views.getInstance().displayObject(eobject))
			{
				LayoutData targetLayoutData = LayoutDataManager.getLayoutDataForView(
						weeditor, (GraphicalElement) eobject, dest_viewID);
				LayoutData sourceLayoutData = LayoutDataManager.getLayoutDataForView(
						weeditor, (GraphicalElement) eobject, src_viewID);

				// if source is already initialized and either everything should
				// be
				// imported or only new layoutdata should be imported and the
				// layoutdata
				// is new (not initialized)
				if (sourceLayoutData.isInitialized()
						&& (!onlyNew || !targetLayoutData.isInitialized()))
				{
					LayoutData source = ViewFactoryImpl.eINSTANCE.createLayoutData();
					LayoutDataManager.transferLayoutDataValues(sourceLayoutData, source);

					// put copy of the source and the target in the table
					layoutData.put(source, targetLayoutData);
				}
			}
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#execute()
	 */
	@Override
	public void execute()
	{
		layoutData = new HashMap();

		// prepare the layout of all scopes in the hashtable
		for (Scope scope : selectedScopes)
		{
			layoutScope(scope);
		}

		// import layoutdata (by switching import source and original data)
		redo();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#redo()
	 */
	@Override
	public void redo()
	{
		// switch layoutdata of sourcecopy and target
		for (Object src : layoutData.keySet())
		{
			LayoutData source = (LayoutData) src;
			LayoutData target = (LayoutData) layoutData.get(src);
			LayoutData temp = ViewFactoryImpl.eINSTANCE.createLayoutData();

			LayoutDataManager.transferLayoutDataValues(source, temp);
			LayoutDataManager.transferLayoutDataValues(target, source);
			LayoutDataManager.transferLayoutDataValues(temp, target);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#undo()
	 */
	@Override
	public void undo()
	{
		// switch layoutdata
		redo();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#dispose()
	 */
	@Override
	public void dispose()
	{
		layoutData.clear();
		layoutData = null;

		selectedScopes.clear();
		selectedScopes = null;

		super.dispose();
	}
}
