/**
 * File:    ImportTemplateCommand.java
 * Created: 11.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.template;

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

import org.eclipse.gef.commands.Command;
import org.eclipse.jwt.meta.commands.interfaces.IInterruptibleCommand;
import org.eclipse.jwt.we.model.view.Diagram;

/**
 * Import a workflow template into the current workflow
 * 
 * @version $Id: ImportTemplateCommand.java,v 1.4 2009/11/26 12:41:53 chsaad Exp
 *          $
 * @author Christian Saad (csaad@gmx.net), Programming distributed Systems Lab,
 *         University of Augsburg, Germany, www.ds-lab.org
 */
public class ImportTemplateCommand extends Command implements IInterruptibleCommand
{

	/**
	 * The subpackages to be added.
	 */
	private ArrayList packages;

	/**
	 * The elements to be added.
	 */
	private ArrayList elements;

	/**
	 * The comments to be added.
	 */
	private ArrayList comments;

	/**
	 * The references to be added.
	 */
	private ArrayList references;

	/**
	 * The referenceedges to be added.
	 */
	private ArrayList referenceedges;

	/**
	 * The layoutdatas to be added.
	 */
	private ArrayList layoutdatas;

	/**
	 * The target package.
	 */
	private org.eclipse.jwt.meta.model.core.Package targetModel;

	/**
	 * The target diagram.
	 */
	private Diagram targetDiagram;


	/**
	 * Constructor
	 * 
	 * @param targetModel
	 *            The target package.
	 * @param templateModel
	 *            The source package.
	 */
	public ImportTemplateCommand(org.eclipse.jwt.meta.model.core.Package targetModel,
			Diagram targetDiagram, org.eclipse.jwt.meta.model.core.Package templateModel,
			Diagram templateDiagram)
	{
		super("Import Template"); //$NON-NLS-1$

		packages = new ArrayList();
		elements = new ArrayList();
		comments = new ArrayList();
		references = new ArrayList();
		referenceedges = new ArrayList();
		layoutdatas = new ArrayList();

		packages.addAll(templateModel.getSubpackages());
		elements.addAll(templateModel.getElements());
		comments.addAll(templateModel.getOwnedComment());

		if (templateDiagram != null)
		{
			references.addAll(templateDiagram.getReferences());
			referenceedges.addAll(templateDiagram.getReferenceEdges());
			layoutdatas.addAll(templateDiagram.getLayoutData());
		}

		this.targetModel = targetModel;
		this.targetDiagram = targetDiagram;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.eclipse.jwt.we.commands.interfaces.IInterruptibleCommand#
	 * checkIfCommandCanBeExecuted()
	 */
	public boolean checkIfCommandCanBeExecuted()
	{
		return true;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#execute()
	 */
	@Override
	public void execute()
	{
		targetModel.getSubpackages().addAll(packages);
		mergePackages(targetModel);
		targetModel.getElements().addAll(elements);
		targetModel.getOwnedComment().addAll(comments);

		if (targetDiagram != null)
		{
			targetDiagram.getReferences().addAll(references);
			targetDiagram.getReferenceEdges().addAll(referenceedges);
			targetDiagram.getLayoutData().addAll(layoutdatas);
		}
	}


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


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.commands.Command#undo()
	 */
	@Override
	public void undo()
	{
		targetModel.getSubpackages().removeAll(packages);
		targetModel.getElements().removeAll(elements);
		targetModel.getOwnedComment().removeAll(comments);

		if (targetDiagram != null)
		{
			targetDiagram.getReferences().removeAll(references);
			targetDiagram.getReferenceEdges().removeAll(referenceedges);
			targetDiagram.getLayoutData().removeAll(layoutdatas);
		}
	}
	
	/**
	 * if two packages in the same hierarchy have the same name, then merge these packages
	 * @param superPackage
	 */
	private void mergePackages(org.eclipse.jwt.meta.model.core.Package superPackage) {
		List<org.eclipse.jwt.meta.model.core.Package> setOfPackagesToRemove = new ArrayList<org.eclipse.jwt.meta.model.core.Package>();
		for (int i=0; i < superPackage.getSubpackages().size(); i++) {
			if (i<superPackage.getSubpackages().size()-1)
			  for (int j=i+1; j < superPackage.getSubpackages().size(); j++) {
				if (superPackage.getSubpackages().get(i).getName()
						.equals(superPackage.getSubpackages().get(j).getName())) {
					//merge these packages: add all sub packages of j to i
					superPackage.getSubpackages().get(i).getSubpackages().addAll(
							superPackage.getSubpackages().get(j).getSubpackages());
					//add all elements of j to i
					superPackage.getSubpackages().get(i).getElements().addAll(
							superPackage.getSubpackages().get(j).getElements());
					//add j to the list of packages that shall be removed
					setOfPackagesToRemove.add(superPackage.getSubpackages().get(j));
				
				}
			}
			//recursive call for all subpackages
			mergePackages(superPackage.getSubpackages().get(i));
		}
		//remove the packages which content has been added to another place
		superPackage.getSubpackages().removeAll(setOfPackagesToRemove);
	}

}