/*------------------------------------------------------------------------------
  -
  - Copyright (c) 2015-2016 University of Padova, ITALY -  Intecs SpA 
  - All rights reserved. This program and the accompanying materials
  - are made available under the terms of the Eclipse Public License v2.0
  - which accompanies this distribution, and is available at
  - http://www.eclipse.org/legal/epl-v20.html
  -
  - Contributors:
  -
  - Alessandro Zovi azovi@math.unipd.it
  - Stefano Puri stefano.puri@intecs.it
  - Laura Baracchi laura.baracchi@intecs.it
  - Nicholas Pacini nicholas.pacini@intecs.it  
  -
  - Initial API and implementation and/or initial documentation
  ------------------------------------------------------------------------------*/package org.polarsys.chess.multicore.partitioning;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * The Class WorstFitBinPacker.
 */
public class WorstFitBinPacker implements BinPacker {
	
	/** The decreasing ordering. */
	private final boolean DECREASING_ORDERING = true; 

//	@Override
//	public Map<Bin, List<Task>> pack(List<Bin> bins, List<Task> tasks) {		
//		
//		Map<Bin, List<Task>> toReturn = new Hashtable<Bin, List<Task>> ();
//		// init output
//		for(Bin bin : bins)
//			toReturn.put(bin, new ArrayList<Task>());
//		
//		
//		if(tasks.size() <= bins.size()){ // trivial packing
//			int i =0;
//			for(Task task : tasks){
//				Bin bin = bins.get(i);
//				ArrayList<Task> theList = new ArrayList<Task>();
//				theList.add(task);
//				bin.setCapacity(bin.getCapacity()+task.computeU());
//				toReturn.put(bin, theList);
//				i++;
//			}
//		} else {// nominal case
//			
//			// sort the tasks by increasing/decreasing utilisation
//			Object[] allTasks = tasks.toArray();
//			//Arrays.sort(allTasks);
//			Arrays.sort(allTasks, new Comparator<Object>() {
//
//				@Override
//				public int compare(Object o1, Object o2) {
//					if(DECREASING_ORDERING)
//						return -(((Task)o1).computeU()).compareTo(((Task)o2).computeU());
//					else
//						return (((Task)o1).computeU()).compareTo(((Task)o2).computeU());
//				}
//			});
//			
//			int indexEmptiestBin = 0;
//			float emptiestCapacity = 0.0f;
//			Object[] allBins = bins.toArray();
//			
//			
//			for(int taskIndex = 0; taskIndex < allTasks.length; taskIndex++){
//				
//				Task task = (Task)allTasks[taskIndex];
//				boolean found = false;
//				
//				Bin bin = (Bin)allBins[indexEmptiestBin];
//				// try with emptiest bin
//				if(bin.getCapacity() + task.computeU() <= bin.getSize())
//					found = true;
//				else { //try with other bins 
//					for(int indexCurrentBin = 0; indexCurrentBin < allBins.length; indexCurrentBin++){
//						if (indexCurrentBin == indexEmptiestBin) // already visited
//							continue;
//						bin =(Bin)allBins[indexCurrentBin];
//						if(bin.getCapacity() + task.computeU() <= bin.getSize()){
//							found = true;
//							break;
//						}
//					}
//				}
//				
//				if(!found)
//					System.out.println("PACKING FAILED");
//				else {
//					task.setOwner(bin);
//					bin.setCapacity(bin.getCapacity()+task.computeU());
//					// store to output
//					List<Task> theTasks = toReturn.get(bin);
//					theTasks.add(task);
//					toReturn.put(bin, theTasks);
//					found = true;
//					// update info on emptiest bin
//					emptiestCapacity = Float.MAX_VALUE;
//					for(int binIndex = 0; binIndex < allBins.length; binIndex++){
//						float currentCapacity = ((Bin)allBins[binIndex]).getCapacity();
//						if(currentCapacity < emptiestCapacity){
//							emptiestCapacity = currentCapacity;
//							indexEmptiestBin = binIndex;
//						}
//					}
//				}
//			}
//			
//		}
//		return toReturn;
//	}

	/* (non-Javadoc)
 * @see org.polarsys.chess.multicore.partitioning.BinPacker#pack(java.util.List, java.util.List)
 */
@Override
	public Map<Bin, List<Task>> pack(List<Bin> bins, List<Task> tasks) {		
		
		Map<Bin, List<Task>> toReturn = new Hashtable<Bin, List<Task>> ();
		
		// init output
//		for(Bin bin : bins)
//			toReturn.put(bin, new ArrayList<Task>());
		
		
		if(tasks.size() <= bins.size()){ // trivial packing
			int i =0;
			for(Task task : tasks){
				Bin bin = bins.get(i);
				ArrayList<Task> theList = new ArrayList<Task>();
				theList.add(task);
				bin.setCapacity(bin.getCapacity()+task.getU());
				toReturn.put(bin, theList);
				i++;
			}
		} else {// nominal case
			
			// sort the tasks by increasing/decreasing utilization
			Object[] allTasks = tasks.toArray();
			//Arrays.sort(allTasks);
			Arrays.sort(allTasks, new Comparator<Object>() {

				@Override
				public int compare(Object o1, Object o2) {
					if(DECREASING_ORDERING)
						return -(((Task)o1).getU()).compareTo(((Task)o2).getU());
					else
						return (((Task)o1).getU()).compareTo(((Task)o2).getU());
				}
			});
			
			int indexEmptiestBin = 0;
			float emptiestCapacity = 0.0f;
			Object[] allBins = {new Bin(indexEmptiestBin)}; // ensure there is at least 1 bin even in case an empty list has been passed (this is the case during RUN reduction)
			int indexLastBin = 0;
			if(bins.size() > 0){
				allBins = bins.toArray();
				indexLastBin = bins.size()-1;
			}
				
			
			
			for(int taskIndex = 0; taskIndex < allTasks.length; taskIndex++){
				
				Task task = (Task)allTasks[taskIndex];
				Bin bin = (Bin)allBins[indexEmptiestBin];
				// try with emptiest bin
				if(bin.getCapacity() + task.getU() <= bin.getSize()){
					task.setOwner(bin);
					bin.setCapacity(bin.getCapacity()+task.getU());
					// store to output
					List<Task> theTasks = toReturn.get(bin);
					if(theTasks == null) // needed because we don't initialize toReturn at the beginning, to provide input/output of variable size
						theTasks = new ArrayList<Task>();
					theTasks.add(task);
					toReturn.put(bin, theTasks);
				}
				else {
					//System.out.println("PARTITIONING FAILED, OPENING NEW BIN");
					// open new bin
					Bin newBin = new Bin(new Integer(++indexLastBin));
					task.setOwner(newBin);
					newBin.setCapacity(newBin.getCapacity()+task.getU());
					ArrayList<Task> theList = new ArrayList<Task>();
					theList.add(task);
					toReturn.put(newBin, theList);
					
					// add bin to the common array 
					Object[] tmpBinArray = Arrays.copyOf(allBins, allBins.length + 1);
					assert(tmpBinArray.length -1 == indexLastBin);
					tmpBinArray[indexLastBin] = newBin;
					allBins = tmpBinArray;
				}
				
				// update info on emptiest bin
				emptiestCapacity = Float.MAX_VALUE;
				for(int binIndex = 0; binIndex < allBins.length; binIndex++){
					float currentCapacity = ((Bin)allBins[binIndex]).getCapacity();
					if(currentCapacity < emptiestCapacity){
						emptiestCapacity = currentCapacity;
						indexEmptiestBin = binIndex;
					}
				}
			}
			
		}
		return toReturn;
	}
}
