package tvark.old;

import java.io.*;

public class MIG {
	private Schedule initial;

	private Schedule current;

	private Schedule best;
	
	private ScheduleData data;
	private XmlFileOut analize, summary;
	private Student[] students;

	private int PStud = 5, PTeach = 8, POff= 10, PMax = 8; 
	private int MaxLimit=11;
	private Property prop;

	boolean baig=false;	
	
	public MIG(Schedule start,Property prop) {
		this.prop = prop;
		this.PTeach= prop.getPTeach();
		this.PStud=prop.getPStud();
		this.POff = prop.getPOff();
		this.PMax = prop.getPMax();
		this.MaxLimit=prop.getMaxLimit();
		
		
		System.out.println("Starting MIG Optimization Process... ");
		data = start.getData();
		students = data.getStudents();
		initial = start.clone();
		serialize(initial, prop.getRootdir()+"/"+initial.getFolder()+"/initial.ser");
		analize= new XmlFileOut(initial.getFolder()+"/Analisis.xml",prop.getRootdir());
		summary= new XmlFileOut(start.getFolder()+"/Summary_MIG.xml", prop.getRootdir());
		
		current = start;
		best = new Schedule();

		System.out.println("Data collected... Process Started... ");

		
		int iterations = 0;
		
		int Penalty = current.countPenalty(prop);
		//printXML(iterations, Penalty);
		int CurPenalty = 0;
		best = current.clone();
		serialize(best, prop.getRootdir()+"/"+initial.getFolder()+"/best.ser");

		for (int i = 0; i < prop.getIter(); i++) 
		{	
			System.out.println("iteracija"+ i);
	//------------------------------------		
		//	if (n > data.getStudents().length * K) break;
		//	if (iterations >= prop.getIter())break;
			
			for (int j = 0; j < students.length; j++) {
			
				PointSt[] wind = current.findStudentWindow(j);

			for(int w=0; w< wind.length; w++)
			{
			//	if (iterations >= prop.getIter())break;
			//	double Random = Math.random();
				
				if (wind[w].isPointSt()) {
					PointSt[] points = current.findAnyFillStud(j);
					boolean flag = true;
					for (int k = 0; k < points.length; k++) 
					{
						if (current.testMoveStudent(points[k], wind[w]) && flag )
							{
								flag = false;
								current.moveStudent(points[k], wind[w]);
								CurPenalty =current.countPenalty(prop);
								if (Penalty < CurPenalty){
									current.UnDoMoveStud(wind[w], points[k]);
								}	
								break;
							}
					}
				}
//-----------------------------------------------				
					CurPenalty = current.countPenalty(prop);
					if (Penalty > CurPenalty) {
		//				n = 0;
						System.out.println("						Got better: -"+ (Penalty-CurPenalty)+ " Points");
						printXML(iterations, CurPenalty);
						best = current.clone();
						serialize(best, prop.getRootdir()+"/"+initial.getFolder()+"/best.ser");
						Penalty = CurPenalty;
					}else if(Penalty < CurPenalty){
						System.out.println("		             Got worse: -"+ (Penalty-CurPenalty)+ " Points");
					}

			   }					
			}	//--mokinio
			
		}		//---iterac
		
		initial = readSerialized(prop.getRootdir()+"/"+initial.getFolder()+"/initial.ser");
		best = readSerialized(prop.getRootdir()+"/"+initial.getFolder()+"/best.ser");

		System.out.print("Testing Teachers: ");
		if(best.testTeach()){ System.out.println("Pass");
		}else {
			System.out.println("Fail");
		}
		
		System.out.print("Testing Students: ");
		if(best.testStud()){ System.out.println("Pass");
		}else {
			System.out.println("Fail");
		}
		

		System.out.println("Process Finished... ");
		printXML("MIG Summary: ");
		printXML("Optimized by Students : Penalty for Teacher Window - "+PTeach+ "; Students window - "+PStud+";");
		printXML("Penalty for working hour on the day off "+POff+" Penalty for Hour Limit: "+ PMax);
		printXML("Iterations:               " + iterations);
		printXML("Teacher Windows Initial:  " + initial.teachWindow());
		printXML("Teacher Windows Best:     " + best.teachWindow());
		printXML("Student Windows Initial:  " + initial.studWindow());
		printXML("Student Windows Best:     " + best.studWindow());
		printXML("Teacher OFF Initial:     " + initial.countOff());
		printXML("Teacher OFF Best:     " + best.countOff());
		printXML("Over Max Limit Initial:  " + initial.overMaxLimit(MaxLimit));
		printXML("Over Max Limit Best:     " + best.overMaxLimit(MaxLimit));
		printXML("Initial Penalty Points............"
				+initial.countPenalty(prop));
		printXML("Optimized Penalty Points.........." + Penalty);
		best.printSubjGroupsXML("best.xml");
		analize.close();
		summary.close();
	//	serialize(best, prop.getRootdir()+"//MIG_best"+Calendar.getInstance().getTime().toString().replace(":", "_")+".ser");
		
		File f = new File(prop.getRootdir()+"/"+best.getFolder()+"/students_optimized");
		if (f.mkdir()) {
			System.out.println("Dir /"+best.getFolder()+"/students_optimized Created");
		} else {
			System.out
					.println("Dir /"+best.getFolder()+"/students_optimized NOT Created OR it already  Exists");
		}
		for (int i = 0; i < data.getStudents().length; i++) {
			best.printStudentXML(data.getStudents()[i], "students_optimized");
		}

		f = new File(prop.getRootdir()+"/"+best.getFolder()+"/teachers_optimized");
		if (f.mkdir()) {
			System.out.println("Dir /"+best.getFolder()+"/teachers_optimized Created");
		} else {
			System.out
					.println("Dir /"+best.getFolder()+"/teachers_optimized NOT Created OR it already Exists");
		}
		for (int i = 0; i < data.getTeachers().length; i++) {
			best.printTeacherXML(data.getTeachers()[i], "teachers_optimized");
		}
		
		
		f = new File(prop.getRootdir()+"/"+best.getFolder()+"/rooms_optimized");
		if (f.mkdir()) 
		{
			System.out.println("Dir /"+best.getFolder()+"/rooms_optimized Created");
		} else 
		{
			System.out.println("Dir /"+best.getFolder()+"/rooms_optimized NOT Created OR it already Exists");
		}
		for (int i = 0; i < data.getRooms().length; i++) 
		{
			best.printRoomXML(data.getRooms()[i], "rooms_optimized");
		
		}		
	
	}

	public MIG() {

	}

	public void serialize(Schedule serial, String filename) {
		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = new FileOutputStream(filename);
			out = new ObjectOutputStream(fos);
			out.writeObject(serial);
			out.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}

	}

	public Schedule readSerialized(String filename) {
		
		Schedule ret = new Schedule();

		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {
			fis = new FileInputStream(filename);
			in = new ObjectInputStream(fis);
			ret = (Schedule) in.readObject();
			in.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		} catch (ClassNotFoundException ex) {
			ex.printStackTrace();
		}

		return ret;
	}

	
	public void printXML(int iter, int penalty){
		analize.startRow();
		analize.addTag(Integer.toString(iter));
		analize.addTag(Integer.toString(penalty));
		analize.endRow();
		
	}
	
	public void printXML(String in){
		summary.startRow();
		summary.addTag(in);
		summary.endRow();
		
	}

	

	public Schedule getBest() {
		return best;
	}

	public Schedule getInitial() {
		return initial;
	}

}
