/*******************************************************************************
 * Copyright (c) 2008 SAS Institute Inc.
 * 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:
 *     SAS Institute Inc. - initial API and implementation
 ******************************************************************************/
package org.eclipse.cosmos.me.provisional.deployment.sdd.tooling.btg.aggregator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.DeploymentDescriptor;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.Resource;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.CompositeInstallable;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.InstallableUnit;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.LocalizationUnit;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.ConfigurationUnit;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.ResultingResource;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.variable.ParameterGroup;



public class CompositeInstallableType {
	//TODO Update class to get out languages
	public static Collection <CompositeInstallable> merge(Collection <CompositeInstallable> compositeInstallables1, Collection <CompositeInstallable> compositeInstallables2)
	{
		/*<CompositeInstallableType> 	 	 	 	
		id 	xsd:ID 	Throw Away
		operation 	<OperationType> 	Yes
		any 	namespace="##other" 	 ?
		Identity 		<IdentityType> 	Merge
		Condition 		<ConditionType> 	Merge
		Variables 		<VariablesType> 	Merge
		RequiredBase 		<RequiredBaseType> 	Merge
		Requirements 		<RequirementsType> 	Merge
		Languages 		<LanguageSelectionsType> 	Merge
		Completion 		<CompletionType> 	Merge
		ResultingResource 		<ResultingResourceType> 	Yes
		ResultingChange 		<ResultingChangeType> 	Yes
		BaseContent 		<BaseContentType> 	Merge
		SelectableContent 		<SelectableContentType> 	Merge
		LocalizationContent 		<LocalizationContentType> 	Merge 
		*/
		
		Collection <CompositeInstallable> compositeInstallablesToRemove = new ArrayList <CompositeInstallable> ();
		Iterator <CompositeInstallable> compositeInstallableIter1 = compositeInstallables1.iterator();		
		//iterate through the compositeInstallables
		while (compositeInstallableIter1.hasNext())
		{
			CompositeInstallable compositeInstallable1 = (CompositeInstallable) compositeInstallableIter1.next();
			Iterator <CompositeInstallable> compositeInstallableIter2 = compositeInstallables2.iterator();
			while (compositeInstallableIter2.hasNext())
			{
				CompositeInstallable compositeInstallable2 = (CompositeInstallable) compositeInstallableIter2.next();
				//if you find a match that hasn't been found, note it
				//one of the equals needs to be deleted with its children merged over
				if (compositeInstallablesToRemove.contains(compositeInstallable2)==false)
				{
					if (equals(compositeInstallable1, compositeInstallable2))
					{  //merge what is needed
						compositeInstallablesToRemove.add(compositeInstallable2);						
												
						compositeInstallable1 = merge(compositeInstallable1,compositeInstallable2);
					}
				}
					
			}
		}
		
		compositeInstallables2.removeAll(compositeInstallablesToRemove);
		//remove all of the matches that were found
		
		Collection <CompositeInstallable> finalCompositeInstallables = new ArrayList <CompositeInstallable> ();
		//create and return a new collection with all of the remaining items
		finalCompositeInstallables.addAll(compositeInstallables1);
		finalCompositeInstallables.addAll(compositeInstallables2);		
		
		return finalCompositeInstallables;
		
	}
	
	public static boolean equals(CompositeInstallable iu1, CompositeInstallable iu2)
	{
		/*
		 <xsd:sequence>
		    <xsd:element name="Identity" type="sdd-common:IdentityType" minOccurs="0"/>
		    <xsd:element name="Condition" type="sdd-dd:ConditionType" minOccurs="0"/>
		    <xsd:element name="Variables" type="sdd-dd:VariablesType" minOccurs="0"/>
		    <xsd:element name="RequiredBase" type="sdd-dd:RequiredBaseType" minOccurs="0"/>
		    <xsd:element name="Requirements" type="sdd-dd:RequirementsType" minOccurs="0"/>
		    <xsd:element name="Languages" type="sdd-dd:LanguageSelectionsType" minOccurs="0"/>
		    <xsd:element name="ResultingResource" type="sdd-dd:ResultingResourceType" minOccurs="0" maxOccurs="unbounded"/>
		    <xsd:element name="ResultingChange" type="sdd-dd:ResultingChangeType" minOccurs="0" maxOccurs="unbounded"/>
		    <xsd:element name="BaseContent" type="sdd-dd:BaseContentType" minOccurs="0"/>
		    <xsd:element name="SelectableContent" type="sdd-dd:SelectableContentType" minOccurs="0"/>
		    <xsd:element name="LocalizationContent" type="sdd-dd:LocalizationContentType" minOccurs="0"/>
  		</xsd:sequence>
		<xsd:attribute name="id" type="xsd:ID" use="required"/>
		<xsd:attribute name="operation" type="sdd-dd:OperationType" use="required"/>
		<xsd:anyAttribute namespace="##other" processContents="lax"/>
 
		  
		<CompositeInstallableType> 	 	 	 	
		id 	xsd:ID 	Throw Away
		operation 	<OperationType> 	Yes
		any 	namespace="##other" 	 ?
		Identity 		<IdentityType> 	Merge
		Condition 		<ConditionType> 	Merge
		Variables 		<VariablesType> 	Merge
		RequiredBase 		<RequiredBaseType> 	Merge
		Requirements 		<RequirementsType> 	Merge
		Languages 		<LanguageSelectionsType> 	Merge
		Completion 		<CompletionType> 	Merge
		ResultingResource 		<ResultingResourceType> 	Yes
		ResultingChange 		<ResultingChangeType> 	Yes
		BaseContent 		<BaseContentType> 	Merge
		SelectableContent 		<SelectableContentType> 	Merge
		LocalizationContent 		<LocalizationContentType> 	Merge 
		*/
		
		if (StringType.equals(iu1.getOperation(), iu2.getOperation()))
		{
			if ((iu1.getResultingResources()== null)&&(iu1.getResultingResources()!=null))
				return false;
			if ((iu1.getResultingResources()!= null)&&(iu1.getResultingResources()==null))
				return false;
			if ((iu1.getResultingResources()!= null)&&(iu1.getResultingResources()!=null))
			{
				if ((ResultingResourceType.equals(iu1.getResultingResources(), iu2.getResultingResources()))==false)
				{
					return false;
				}
			}
			
			if ((iu1.getResultingChanges()== null)&&(iu1.getResultingChanges()!=null))
				return false;
			if ((iu1.getResultingChanges()!= null)&&(iu1.getResultingChanges()==null))
				return false;
			if ((iu1.getResultingChanges()!= null)&&(iu1.getResultingChanges()!=null))
			{
				if ((ResultingChangeType.equals(iu1.getResultingChanges(), iu2.getResultingChanges()))==false)
				{
					return false;
				}
			}
			
			return true;
		}
		else return false;
		
		
	}
	
	public static CompositeInstallable merge(CompositeInstallable compositeInstallable1, CompositeInstallable compositeInstallable2)
	{
		compositeInstallable1.setIdentityData(IdentityType.merge(compositeInstallable1.getIdentityData(), compositeInstallable2.getIdentityData()));
		compositeInstallable1.setCondition(ConditionType.merge(compositeInstallable1.getCondition(), compositeInstallable2.getCondition()));
		compositeInstallable1.setDerivedVariables(DerivedVariableType.merge(compositeInstallable1.getDerivedVariables(), compositeInstallable2.getDerivedVariables()));
		compositeInstallable1.setResourceProperties(ResourcePropertyType.merge(compositeInstallable1.getResourceProperties(), compositeInstallable2.getResourceProperties()));
		ParameterGroup params = ParameterGroupType.merge(compositeInstallable1.getParameterGroups(), compositeInstallable2.getParameterGroups());
		ArrayList <ParameterGroup> myParams = new ArrayList <ParameterGroup> ();
		myParams.add(params);
		compositeInstallable1.setParameterGroups(myParams);
		compositeInstallable1.setRequiredBase(RequiredBaseType.merge(compositeInstallable1.getRequiredBase(), compositeInstallable2.getRequiredBase()));
		compositeInstallable1.setRequirements(RequirementType.merge(compositeInstallable1.getRequirements(), compositeInstallable2.getRequirements()));
		compositeInstallable1.setMandatoryLanguages(LanguageType.merge(compositeInstallable1.getMandatoryLanguages(), compositeInstallable2.getMandatoryLanguages()));
		compositeInstallable1.setOptionalLanguages(LanguageType.merge(compositeInstallable1.getOptionalLanguages(), compositeInstallable2.getOptionalLanguages()));
		
		compositeInstallable1.setBaseCompositeUnits(CompositeUnitType.merge(compositeInstallable1.getBaseCompositeUnits(), compositeInstallable2.getBaseCompositeUnits()));
		compositeInstallable1.setBaseConfigurationUnits(ConfigurationUnitType.merge(compositeInstallable1.getBaseConfigurationUnits(), compositeInstallable2.getBaseConfigurationUnits()));
		compositeInstallable1.setBaseContainedPackages(ReferencedPackageType.merge(compositeInstallable1.getBaseContainedPackages(), compositeInstallable2.getBaseContainedPackages()));
		compositeInstallable1.setBaseInstallableUnits(InstallableUnitType.merge(compositeInstallable1.getBaseInstallableUnits(), compositeInstallable2.getBaseInstallableUnits()));
		
		compositeInstallable1.setSelectableCompositeUnits(CompositeUnitType.merge(compositeInstallable1.getSelectableCompositeUnits(), compositeInstallable2.getSelectableCompositeUnits()));
		compositeInstallable1.setSelectableConfigurationUnits(ConfigurationUnitType.merge(compositeInstallable1.getSelectableConfigurationUnits(), compositeInstallable2.getSelectableConfigurationUnits()));
		compositeInstallable1.setSelectableContainedPackages(ReferencedPackageType.merge(compositeInstallable1.getSelectableContainedPackages(), compositeInstallable2.getSelectableContainedPackages()));
		compositeInstallable1.setSelectableInstallableUnits(InstallableUnitType.merge(compositeInstallable1.getSelectableInstallableUnits(), compositeInstallable2.getSelectableInstallableUnits()));
		
		compositeInstallable1.setLocalizationUnits(LocalizationUnitType.merge(compositeInstallable1.getLocalizationUnits(), compositeInstallable2.getLocalizationUnits()));
		return compositeInstallable1;
	}
	
}
