package tvark.beans;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;

import tvark.jsf.JsfUtils;
import tvark.old.Property;
import tvark.old.Schedule;

public abstract class MethodParamsBean {
	
	private static int toInt(Number pNumber) {
		if (pNumber == null) {
			return 0;
		}
		return pNumber.intValue();
	}
	
	private UploadBean mUploadBean;	
	private ParametersBean mParametersBean;
	private ParamsMCBean mParamsMCBean;	
	private ParamsBayesBean mParamsBayesBean;	
	private ParamsSABean mParamsSABean;	
	private ResultsBean mResultsBean;
	
	public void loadBeans() {
		
		mUploadBean = JsfUtils.getValue("#{uploadBean}", UploadBean.class);		
		mParametersBean = JsfUtils.getValue("#{parametersBean}", ParametersBean.class);
		mParamsMCBean = JsfUtils.getValue("#{paramsMcBean}", ParamsMCBean.class);
		mParamsBayesBean = JsfUtils.getValue("#{paramsBayesBean}", ParamsBayesBean.class);;
		mParamsSABean = JsfUtils.getValue("#{paramsSaBean}", ParamsSABean.class);;
		mResultsBean = JsfUtils.getValue("#{resultsBean}", ResultsBean.class);;
		
	}

	
	protected abstract Schedule execute(Schedule pSchedule, Property pProperty);
	
	public final String set() throws IOException {
		loadBeans();
		
		String tempDir = System.getProperty("java.io.tmpdir");
		
		File folder = new File(tempDir + "/" + UUID.randomUUID().toString()).getAbsoluteFile();
		folder.mkdir();
		
		if (!folder.exists() || folder.isFile()) {
			return null;
		}
		
		String fileName = "input.xml";
		FileOutputStream os = new FileOutputStream(fileName);
		os.write(mUploadBean.getBytes());
		os.close();
		Schedule initialSchedule = new Schedule(fileName, folder.getParent(), mParametersBean.getNumberOfRooms().intValue(), folder.getName());
		Schedule tempInitialSchedule = cloneSchedule(initialSchedule);
		
		Property property = new Property(
				toInt(mParametersBean.getStudentGap()),
				toInt(mParametersBean.getTeacherGap()),
				toInt(mParametersBean.getpedagoginesDidaktikos()),
				toInt(mParametersBean.getDayOffViolation()),
				toInt(mParametersBean.getExceedingHourLimit()),
				toInt(mParametersBean.getHourLimit()),
				folder.getParent(),
				toInt(mParamsSABean.getInitialTemperature()),
				toInt(mParamsMCBean.getIterations()),
				toInt(this == mParamsSABean ? mParamsSABean.getIterations() : mParamsBayesBean.getIterationsSa()),
				toInt(mParamsBayesBean.getIterationsBayes()),
				toInt(mParamsSABean.getCoolingRate()),
				toInt(mParamsBayesBean.getmBayes_on()),
				toInt(mParamsBayesBean.getBayesX1()),
				toInt(mParamsBayesBean.getBayesY1()),
				toInt(mParamsBayesBean.getBayesX2()),
				toInt(mParamsBayesBean.getBayesY2()),
				toInt(mParamsBayesBean.getbayes_best()),
				toInt(mParamsBayesBean.getbayes_best_current()),
				toInt(mParametersBean.getPPInitial()));
		
		Schedule tempNewSchedule = execute(tempInitialSchedule, property);
		Schedule newSchedule = cloneSchedule(tempNewSchedule);
		
		mResultsBean.setSchedules(initialSchedule, newSchedule, property);
		return JsfUtils.Outcome.RESULTS;
	}
	
	private Schedule cloneSchedule(Schedule pSchedule) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		JsfUtils.serialize(pSchedule, bos);
		return (Schedule) JsfUtils.deserialize(new ByteArrayInputStream(bos.toByteArray()));			
	}
}
