/*******************************************************************************
 * 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.contentunit.Completion;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.CompositeInstallable;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.contentunit.CompositeLocalizationUnit;
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;



public class CompositeLocalizationUnitType {
	
	/*
	   <CompositeLocalizationUnitType> 	 	 	 	
		id 	xsd:ID 	Throw Away
		any 	namespace="##other" 	 ?
		Identity 		<IdentityType> 	Merge
		Condition 		<ConditionType> 	Merge
		Variables 		<VariablesType> 	Merge
		RequiredBase 		<RequiredBaseType> 	Merge
		Requirements 		<RequirementsType> 	Merge
		Languages 		<LanguagesType> 	Merge
		Completion 		<CompletionType> 	Merge
		LocalizationBase 		<RequiredBaseType> 	Merge
		ResultingResource 		<ResultingResourceType> 	Yes
		LocalizationUnit 		<LocalizationUnitType> 	Merge
		ContainedLocalizationPackage 		<ReferencedPackageType> 	Merge
		CompositeLocalizationUnit 		<CompositeLocalizationUnitType> 	Merge
		any 		namespace="##other" 	 ?
		
		 <xsd:complexType name="CompositeLocalizationUnitType">
		  <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:LanguagesType" minOccurs="0"/>
		    <xsd:element name="Completion" type="sdd-dd:CompletionType" minOccurs="0" maxOccurs="unbounded"/>
		    <xsd:element name="LocalizationBase" type="sdd-dd:RequiredBaseType" minOccurs="0"/>
		    <xsd:element name="ResultingResource" type="sdd-dd:ResultingResourceType" minOccurs="0" maxOccurs="unbounded"/>
		    <xsd:choice maxOccurs="unbounded">
		      <xsd:element name="LocalizationUnit" type="sdd-dd:LocalizationUnitType"/>
		      <xsd:element name="ContainedLocalizationPackage" type="sdd-dd:ReferencedPackageType"/>
		      <xsd:element name="CompositeLocalizationUnit" type="sdd-dd:CompositeLocalizationUnitType"/>
		    </xsd:choice>
		    <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
		  </xsd:sequence>
		  <xsd:attribute name="id" type="xsd:ID" use="required"/>
		  <xsd:anyAttribute namespace="##other" processContents="lax"/>
		</xsd:complexType>
		 
	 */
	

	private static CompositeLocalizationUnit merge(CompositeLocalizationUnit compositeLocalizationUnit1, CompositeLocalizationUnit compositeLocalizationUnit2)
	{
		
		compositeLocalizationUnit1.setIdentityData(IdentityType.merge(compositeLocalizationUnit1.getIdentityData(),compositeLocalizationUnit2.getIdentityData()));
		compositeLocalizationUnit1.setCondition(ConditionType.merge(compositeLocalizationUnit1.getCondition(), compositeLocalizationUnit1.getCondition()));
		compositeLocalizationUnit1.setConditionalDerivedVariables(ConditionalDerivedVariablesType.merge(compositeLocalizationUnit1.getConditionalDerivedVariables(),compositeLocalizationUnit2.getConditionalDerivedVariables()));
		compositeLocalizationUnit1.setDerivedVariables(DerivedVariableType.merge(compositeLocalizationUnit1.getDerivedVariables(), compositeLocalizationUnit1.getDerivedVariables()));
		compositeLocalizationUnit1.setRequiredBase(RequiredBaseType.merge(compositeLocalizationUnit1.getRequiredBase(), compositeLocalizationUnit2.getRequiredBase()));
		compositeLocalizationUnit1.setRequirements(RequirementType.merge(compositeLocalizationUnit1.getRequirements(), compositeLocalizationUnit2.getRequirements()));
		compositeLocalizationUnit1.setLanguages(LanguageType.merge(compositeLocalizationUnit1.getLanguages(),compositeLocalizationUnit2.getLanguages()));
		compositeLocalizationUnit1.setCompletions(CompletionType.merge(compositeLocalizationUnit1.getCompletions(), compositeLocalizationUnit2.getCompletions()));
		compositeLocalizationUnit1.setLocalizationBase(RequiredBaseType.merge(compositeLocalizationUnit1.getLocalizationBase(), compositeLocalizationUnit1.getLocalizationBase()));
		compositeLocalizationUnit1.setLocalizationUnits(LocalizationUnitType.merge(compositeLocalizationUnit1.getLocalizationUnits(), compositeLocalizationUnit2.getLocalizationUnits()));
		compositeLocalizationUnit1.setContainedLocalizationPackages(ReferencedPackageType.merge(compositeLocalizationUnit1.getContainedLocalizationPackages(), compositeLocalizationUnit2.getContainedLocalizationPackages()));
		compositeLocalizationUnit1.setCompositeLocalizationUnits(CompositeLocalizationUnitType.merge(compositeLocalizationUnit1.getCompositeLocalizationUnits(), compositeLocalizationUnit2.getCompositeLocalizationUnits()));
		
		return compositeLocalizationUnit1;
	}

	public static Collection <CompositeLocalizationUnit> merge(Collection <CompositeLocalizationUnit> compositeLocalizationUnits1, Collection <CompositeLocalizationUnit> compositeLocalizationUnits2)	
	{
		Collection <CompositeLocalizationUnit> compositeLocalizationUnitsToRemove = new ArrayList <CompositeLocalizationUnit> ();
		Iterator <CompositeLocalizationUnit> compositeLocalizationUnitIter1 = compositeLocalizationUnits1.iterator();		
		//iterate through the compositeLocalizationUnits
		while (compositeLocalizationUnitIter1.hasNext())
		{
			CompositeLocalizationUnit compositeLocalizationUnit1 = (CompositeLocalizationUnit) compositeLocalizationUnitIter1.next();
			Iterator <CompositeLocalizationUnit> compositeLocalizationUnitIter2 = compositeLocalizationUnits2.iterator();
			while (compositeLocalizationUnitIter2.hasNext())
			{
				CompositeLocalizationUnit compositeLocalizationUnit2 = (CompositeLocalizationUnit) compositeLocalizationUnitIter2.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 (compositeLocalizationUnitsToRemove.contains(compositeLocalizationUnit2)==false)
				{
					if (equals(compositeLocalizationUnit1, compositeLocalizationUnit2))
					{  //merge hosted compositeLocalizationUnits, types and description groups
						compositeLocalizationUnitsToRemove.add(compositeLocalizationUnit2);						
						compositeLocalizationUnit1 = merge(compositeLocalizationUnit1,compositeLocalizationUnit2);
						
					}
				}
					
			}
		}
		
		compositeLocalizationUnits2.removeAll(compositeLocalizationUnitsToRemove);
		//remove all of the matches that were found
		
		Collection <CompositeLocalizationUnit> finalCompositeLocalizationUnits = new ArrayList <CompositeLocalizationUnit> ();
		//create and return a new collection with all of the remaining items
		finalCompositeLocalizationUnits.addAll(compositeLocalizationUnits1);
		finalCompositeLocalizationUnits.addAll(compositeLocalizationUnits2);		
		
		return finalCompositeLocalizationUnits;
		
	}	

	public static boolean equals(CompositeLocalizationUnit lu1, CompositeLocalizationUnit lu2)
	{
		if ((lu1.getResultingResources()==null)&&(lu2.getResultingResources()!=null))
			return false;
		
		if ((lu2.getResultingResources()==null)&&(lu1.getResultingResources()!=null))
			return false;
		
		if ((lu1.getResultingResources()==null)&&(lu2.getResultingResources()==null))
			return true;
		
		if (ResultingResourceType.equals(lu1.getResultingResources(), lu2.getResultingResources()))
			return true;
		
		return false;
	}
	
}
