package scheduleGenerator;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Contains GenerateSchedule Object
 *
 * @author maurerja.
 *         Created Oct 29, 2012.
 */
public class GenerateSchedule implements Runnable{
	private Config c;
	private int months;
	private ArrayList<Person> p;
	Map<String,ArrayList<String>> available;
	ArrayList<String[]> date;
	private String filename;
	private String currentMonth;

	/**
	 * Responsible for holding information, and using that information to generate a random schedule.
	 *
	 * @param p
	 * @param c
	 * @param numMonths
	 * @param file
	 * @param currentMonth
	 */
	public GenerateSchedule(ArrayList<Person> p,Config c,int numMonths,String file,String currentMonth){
		this.p=p;
		this.c=c;
		this.months=numMonths;
		this.filename = file;
		this.currentMonth = currentMonth;
	}
	//
	@Override
	public void run() {
		this.available = new HashMap<String,ArrayList<String>>();
		this.date = new ArrayList<String[]>();
		for(String cdate: this.c.dates.keySet()){
			//check for inside of months
			//			Calendar today = new GregorianCalendar();
			Calendar curMonthFirstDay = Calendar.getInstance();
			Date d = null; Date d2 = null;
			try {
				d = new SimpleDateFormat("MMM dd, yyyy").parse(cdate);
				d2 = new SimpleDateFormat("MMM").parse(this.currentMonth);
			} catch (ParseException exception) {
				exception.printStackTrace();
			}
			Calendar cal = Calendar.getInstance();
			if (d != null) {
				cal.setTime(d);
			}
			if (d2 != null) {
				curMonthFirstDay.setTime(d2);
			}
			int i = cal.get(Calendar.MONTH);
			//		    Calendar firstDay = (Calendar) cal.clone();
			curMonthFirstDay.set(Calendar.DATE, curMonthFirstDay.getMinimum(Calendar.DATE));
			Calendar lastDay = (Calendar) cal.clone();
			if (i + this.months > 11) {
				lastDay.set(Calendar.YEAR, lastDay.get(Calendar.YEAR) + 1);
			}
			lastDay.set(Calendar.MONTH, (i + this.months) % 11);
			lastDay.set(Calendar.DATE, lastDay.getMaximum(Calendar.DATE));
			if ((curMonthFirstDay.compareTo(cal) > -1) || (curMonthFirstDay.compareTo(lastDay) > -1)) {
				continue;
			}

			for(String ctime: this.c.dates.get(cdate).keySet()){
				for(String cjob:this.c.dates.get(cdate).get(ctime)){
					String[] entry = {cdate,ctime,cjob,"None"};
					this.date.add(entry);
				}
			}
		}
		for(String[] d: this.date){
			ArrayList<String> people = new ArrayList<String>();
			for (Person p: this.p){
				if(p.getAvailability().containsKey(d[0])&& p.getAvailability().get(d[0]).contains(d[1])){
					for (String job: p.getJobs()){
						if (job.equals(d[2])){
							people.add(p.getName());
							break;
						}
					}
				}
			}
			this.available.put(d[0]+d[1]+d[2],people);
		}
		ArrayList<String[]> tempdate=new ArrayList<String[]>();
		for(String[] d: this.date){
			tempdate.add(d);
		}
		while (this.available.size()>0){
			int x;
			String date;
			if (tempdate.size()>0){
				x = getSmallestListIndex(tempdate);
				date = tempdate.get(x)[0]+tempdate.get(x)[1]+tempdate.get(x)[2];}
			else break;
			String person="";
			if(this.available.containsKey(date)&&this.available.get(date).size()>0){
				person = this.available.get(date).get((int)(Math.random()*this.available.get(date).size()));
				this.date.get(this.date.indexOf(tempdate.get(x)))[3]=person;
			}
			for (int i =0; i<tempdate.size();i++){
				String lookingdate=tempdate.get(i)[0]+tempdate.get(i)[1]+tempdate.get(i)[2];
				if (this.available.containsKey(lookingdate)&&
						this.available.get(lookingdate).contains(person))
					this.available.get(lookingdate).remove(person);
				if (this.available.containsKey(lookingdate)&&this.available.get(lookingdate).size()==0){
					this.available.remove(lookingdate);
					i=-1;
				}
			}
			tempdate.remove(x);
		}
		exportSched();
	}

	/**
	 * TODO Put here a description of what this method does.
	 * 
	 * @param date2
	 * 
	 */
	private void exportSched() {
		File file = new File(this.filename);
		// try {
		PrintStream ps = null;
		try {
			ps = new PrintStream(file);
		} catch (FileNotFoundException exception1) {
			exception1.printStackTrace();
		}
		String date = "";
		String time = "";
		for (String[] d : this.date) {
			// try {
			if (!d[0].equals(date)) {
				ps.println("+" + d[0]);
				date = d[0];
			}
			if (!d[1].equals(time)) {
				ps.println("~" + d[1]);
				time = d[1];
			}
			ps.println(":" + d[2] + ";" + d[3]);
			// } catch (IOException exception) {
			// exception.printStackTrace();
			// }
		}
		ps.close();
	}

	private int getSmallestListIndex(ArrayList<String[]> tempdate) {
		int smallest = 0;
		int min = 1000;
		for (int i =0;i<tempdate.size();i++){
			String date = tempdate.get(i)[0]+tempdate.get(i)[1]+tempdate.get(i)[2];
			if (this.available.containsKey(date)&&this.available.get(date).size()<min){
				min = this.available.get(date).size();
				smallest = i;
			}
		}
		return smallest;
	}
}
