package core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeMap;

import datamodel.Interval;
import datamodel.Task;

public class Scheduler {
	
	public static ArrayList<Task> scheduledTasks;
	
	public Scheduler(ArrayList<Task> scheduledTasks){
		Scheduler.scheduledTasks = scheduledTasks;
		Collections.sort(Scheduler.scheduledTasks, Task.Comparators.ScheduledTaskStartTime);
	}
	
	public static HashMap<Integer, ArrayList<Task>> partitionTaskByPriority(ArrayList<Task> todoTasks){
		HashMap<Integer, ArrayList<Task>> paritions = new HashMap<Integer, ArrayList<Task>>();
		for(int i = 0; i < 3; i++){
			ArrayList<Task> partition = new ArrayList<Task>();
			paritions.put(i, partition);
		}
		for(Task task : todoTasks)
			paritions.get(task.getPriority()).add(task);
		return paritions;
	}
	
	public static TreeMap<Long, ArrayList<Task>> partitionTaskByStartTime(ArrayList<Task> todoTasks){
		TreeMap<Long, ArrayList<Task>> partitions = new TreeMap<Long, ArrayList<Task>>();
		for(Task task : todoTasks){
			for(Interval interval : task.getTodoIntervals()){
				long startTime = interval.start;
				ArrayList<Task> partition;
				if(!partitions.containsKey(startTime)){
					partition = new ArrayList<Task>();
					partitions.put(startTime, partition);
				} else
					partition = partitions.get(startTime);
				partition.add(task);
			}
		}
		return partitions;
	}
	
	public static boolean checkIfConflict(long startTime, long endTime, ArrayList<Task> scheduledTasks){
		for(Task scheduledTask : scheduledTasks){
			Interval interval = scheduledTask.getScheduledInterval();
			if((startTime >= interval.start && startTime <= interval.end)
					|| (endTime >= interval.start && endTime <= interval.end))
				return true;
		}
		return false;
	}
	
	public static ArrayList<Task> schedule(ArrayList<Task> todoTasks){
		ArrayList<Task> scheduledTaskThisTime = new ArrayList<Task>();
		// 1. partition todoTask by priority
		HashMap<Integer, ArrayList<Task>> partitionsByPriority = partitionTaskByPriority(todoTasks);
		
		// 2. for tasks with the same priority, partition todoTask by startTime
		for(int i = 2; i >= 0; i--){
			ArrayList<Task> paritionByPriority = partitionsByPriority.get(i);
			TreeMap<Long, ArrayList<Task>> partitionsByStartTime = partitionTaskByStartTime(paritionByPriority);
			for(Long startTime : partitionsByStartTime.keySet()){
				ArrayList<Task> partitionByStartTime = partitionsByStartTime.get(startTime);
				// 3. for tacks with same priority and startTime, sort by durtingTime
				Collections.sort(partitionByStartTime, Task.Comparators.DuringTime);
				for(Task task : partitionByStartTime){
					if(task.isScheduled()){
						partitionByStartTime.remove(task);
						continue;
					} 
					// 4. check if this task can by scheduled in current calendar
					if(!checkIfConflict(startTime, startTime + task.getDuringTime(), Scheduler.scheduledTasks)){
						// 5.if not conflict, schedule todoTask to scheduledTask
						task.setScheduled(true);
						task.setScheduledInterval(new Interval(startTime, startTime + task.getDuringTime()));
						scheduledTaskThisTime.add(task);
						todoTasks.remove(task);
					}
				}
			}
		}
		return scheduledTaskThisTime;
	}
	
	public static void main(String [ ] args){
		
	}
}

@@ -242,16 +242,23 @@
 ledTasks
+ = null
 ;%0A%09%0A%09pub
@@ -261,25 +261,32 @@
 %09public 
-Scheduler
+static void init
 (ArrayLi
@@ -3308,14 +3308,887 @@
 rgs)%7B%0A%09%09
+// Test1%0A%09%09Task task1 = new Task();%0A%09%09ArrayList%3CInterval%3E intervals1 = new ArrayList%3CInterval%3E();%0A%09%09intervals1.add(new Interval(0, 1));%0A%09%09task1.setTodoIntervals(intervals1);%0A%09%09%0A%09%09Task task2 = new Task();%0A%09%09ArrayList%3CInterval%3E intervals2 = new ArrayList%3CInterval%3E();%0A%09%09intervals2.add(new Interval(2, 3));%0A%09%09task2.setTodoIntervals(intervals2);%0A%09%09%0A%09%09Task task3 = new Task();%0A%09%09ArrayList%3CInterval%3E intervals3 = new ArrayList%3CInterval%3E();%0A%09%09intervals3.add(new Interval(5, 9));%0A%09%09task3.setTodoIntervals(intervals3);%0A%09%09%0A%09%09ArrayList%3CTask%3E todoTasks = new ArrayList%3CTask%3E();%0A%09%09todoTasks.add(task1);%0A%09%09todoTasks.add(task2);%0A%09%09todoTasks.add(task3);%0A%09%09%0A%09%09Scheduler.init(new ArrayList%3CTask%3E());%0A%09%09ArrayList%3CTask%3E returnScheduledTasks = Scheduler.schedule(todoTasks);%0A%09%09System.out.println(%22returnScheduledTasks: %22 + returnScheduledTasks);%0A%09%09System.out.println(%22todoTasks: %22 + todoTasks);
 %0A%09%7D%0A%7D%0A

Add first test for task scheduler