/*******************************************************************************
 * 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.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;


import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.Resource;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.TranslatableString;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.requirement.AlternativeRequirement;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.requirement.Requirement;
import org.eclipse.cosmos.me.provisional.deployment.sdd.common.spi.requirement.RequirementResourceConstraint;



public class AlternativeRequirementType {

	public static Collection<AlternativeRequirement> merge(Collection<AlternativeRequirement> alternativeRequirements1, Collection<AlternativeRequirement> alternativeRequirements2)
	{	
		/*
		<AlternativeRequirementType> 	 	 	 	
		id 	xsd:ID 	Throw Away
		priority 	xsd:positiveInteger 	Merge
		any 	namespace="##other" 	 ?
	DisplayElementGroup 		DisplayElementGroup 	Merge
	ResourceConstraint 		<RequirementResourceConstraintType> 	Yes
	Dependency 		<InternalDependencyType> 	Yes
	any 		namespace="##other" 	 ? */
		
		Collection <AlternativeRequirement> alternativeRequirementsToRemove = new ArrayList <AlternativeRequirement> ();
		Iterator <AlternativeRequirement> alternativeRequirementIter1 = alternativeRequirements1.iterator();		
		//iterate through the alternativeRequirements
		while (alternativeRequirementIter1.hasNext())
		{
			AlternativeRequirement alternativeRequirement1 = (AlternativeRequirement) alternativeRequirementIter1.next();
			Iterator <AlternativeRequirement> alternativeRequirementIter2 = alternativeRequirements2.iterator();
			while (alternativeRequirementIter2.hasNext())
			{
				AlternativeRequirement alternativeRequirement2 = (AlternativeRequirement) alternativeRequirementIter2.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 (alternativeRequirementsToRemove.contains(alternativeRequirement2)==false)
				{
					if (equals(alternativeRequirement1, alternativeRequirement2))
					{  //merge hosted alternativeRequirements, types and description groups
						alternativeRequirementsToRemove.add(alternativeRequirement2);						
						alternativeRequirement1 = merge(alternativeRequirement1,alternativeRequirement2);
						
					}
				}
					
			}
		}
		
		alternativeRequirements2.removeAll(alternativeRequirementsToRemove);
		//remove all of the matches that were found
		
		Collection <AlternativeRequirement> finalAlternativeRequirements = new ArrayList <AlternativeRequirement> ();
		//create and return a new collection with all of the remaining items
		finalAlternativeRequirements.addAll(alternativeRequirements1);
		finalAlternativeRequirements.addAll(alternativeRequirements2);		
		
		return finalAlternativeRequirements;
		
	}
	
	public static AlternativeRequirement merge(AlternativeRequirement requirement1, AlternativeRequirement requirement2)
	{	
		
		BigInteger priority = BigInteger.ZERO;
		if (requirement1.getPriority()==null)
			if (requirement2.getPriority()!=null)
				requirement1.setPriority(requirement2.getPriority());
		else if (requirement1.getPriority()!=null)
			if (requirement2.getPriority()!=null)
			{				
				if (requirement1.getPriority().compareTo(requirement2.getPriority())<0)
					priority = requirement2.getPriority();
				else priority = requirement1.getPriority();
			}
		
		if (requirement1.getDescription()==null)
		{
			if (requirement2.getDescription()!=null)		
				requirement1.setDescription(requirement2.getDescription());
		}
		else if (requirement2.getDescription()!=null)
		{
			TranslatableString description = requirement1.getDescription();		
			description.setTranslationKey(description.getTranslationKey()+requirement2.getDescription().getTranslationKey());
			description.setTranslationKey(description.getValue()+requirement2.getDescription().getValue());
			requirement1.setDescription(description);
		}
			
		if (requirement1.getDisplayName()==null)
		{
			if (requirement2.getDisplayName()!=null)		
				requirement1.setDisplayName(requirement2.getDisplayName());
		}
		else if (requirement2.getDescription()!=null)
		{
			TranslatableString value = requirement1.getDisplayName();
			System.out.println(value);
			value.setTranslationKey(value.getTranslationKey()+requirement2.getDisplayName().getTranslationKey());
			value.setTranslationKey(value.getValue()+requirement2.getDisplayName().getValue());
			requirement1.setDisplayName(value);
		}
		
		requirement1.setPriority(priority);
		
		return requirement1;
		
	}
	
	public static boolean equals(AlternativeRequirement requirement1, AlternativeRequirement requirement2)
	{		
	    if (requirement1.getResourceConstraints().size()!=requirement2.getResourceConstraints().size())
	    	return false;
	    else
	    {
		    Iterator<RequirementResourceConstraint> constraintIter1 = requirement1.getResourceConstraints().iterator();
		    while (constraintIter1.hasNext())
		    {			    	
				Iterator<RequirementResourceConstraint> constraintIter2 = requirement2.getResourceConstraints().iterator();
				RequirementResourceConstraint constraint1 = constraintIter1.next();
				boolean foundEquals = false;
				while ((!foundEquals)&&(constraintIter2.hasNext()))
				{
				   if (RequirementResourceConstraintType.equals(constraint1,constraintIter2.next()))
					   foundEquals = true;					  
				}
				if (!foundEquals)
				   return false;
		    }
	    }	    
		return true;				
	}
}





















