package InitialSchedules;

import org.chocosolver.solver.constraints.extension.Tuples;

public class ParametersInitialSchedules {

    int workPeriodsPerDay;
    int shiftWorkPerDay;
    int daysPerSchedule;
    int workPeriodsPerSchedule;
    int totalWorkedPeriodsInSchedule;
    int hoursPerWorkPeriod;

    int fixedCostOfPartTimeEmployeesPerSchedule;
    int hourlyRateOfPartTimeEmployees;
    int minWorkingHoursOfPartTimeEmployeesPerSchedule;
    int maxWorkingHoursOfPartTimeEmployeesPerSchedule;
    int minWorkingPeriodsOfPartTimeEmployeesPerSchedule;
    int maxWorkingPeriodsOfPartTimeEmployeesPerSchedule;

    int fixedCostOfFullTimeEmployeesPerSchedule;
    int regularHourlyRateOfFullTimeEmployees;
    int overtimeHourlyRateOfFullTimeEmployees;
    int workingHoursOfFullTimeEmployeesPerSchedule;
    int maxWorkingHoursOfFullTimeEmployeesPerSchedule;
    int workingPeriodsOfFullTimeEmployeesPerSchedule;
    int maxWorkingPeriodsOfFullTimeEmployeesPerSchedule;

    int workingHoursPaidAtRegularHourlyRatePerSchedule;

    public int[] requiredWorkforce;
    Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees;

    Tuples ValidPartTimeEmployeeShiftTuples;

    public ParametersInitialSchedules() {

        this.setGeneralParameters();
        this.setPartTimeEmployeesParameters();
        this.setFullTimeEmployeesParameters();
        this.setRequiredWorkforce();
        this.setWorkPeriodsSchedulesOfFullTimeEmployees();
        this.setValidPartTimeEmployeeShiftTuples();

    }

    private void setGeneralParameters() {
        this.workPeriodsPerDay = 6;
        this.shiftWorkPerDay = 3;
        this.daysPerSchedule = 14;
        this.hoursPerWorkPeriod = 24 / this.workPeriodsPerDay;
        this.workPeriodsPerSchedule = this.workPeriodsPerDay * this.daysPerSchedule;
    }

    private void setPartTimeEmployeesParameters() {
        this.fixedCostOfPartTimeEmployeesPerSchedule = 50;
        this.hourlyRateOfPartTimeEmployees = 12; // To simulate lower productivity
        this.minWorkingHoursOfPartTimeEmployeesPerSchedule = 32;
        this.maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64;
        this.minWorkingPeriodsOfPartTimeEmployeesPerSchedule
                = (int) (this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
        this.maxWorkingPeriodsOfPartTimeEmployeesPerSchedule
                = (int) (this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
    }

    private void setFullTimeEmployeesParameters() {
        this.fixedCostOfFullTimeEmployeesPerSchedule = 50;
        this.regularHourlyRateOfFullTimeEmployees = 10;
        this.overtimeHourlyRateOfFullTimeEmployees = 15;

        this.workingHoursOfFullTimeEmployeesPerSchedule = 80;
        this.maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120;
        this.workingPeriodsOfFullTimeEmployeesPerSchedule
                = (int) (this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);
        this.maxWorkingPeriodsOfFullTimeEmployeesPerSchedule
                = (int) (this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod);

        this.workingHoursPaidAtRegularHourlyRatePerSchedule = 80;
    }

    private void setRequiredWorkforce() {

        this.requiredWorkforce = new int[this.daysPerSchedule * this.workPeriodsPerDay];
        this.totalWorkedPeriodsInSchedule = 0;
        int[] dailyRequiredWorkforce = new int[]{2, 2, 4, 4, 3, 3};
        for (int day = 0; day < this.daysPerSchedule; day++) {
            for(int shift = 0; shift < this.workPeriodsPerDay; shift++) {
                this.requiredWorkforce[day * this.workPeriodsPerDay + shift] = dailyRequiredWorkforce[shift];
                this.totalWorkedPeriodsInSchedule += dailyRequiredWorkforce[shift];
            }
        }
    }


    private void setWorkPeriodsSchedulesOfFullTimeEmployees() {

        ValidDailySchedules v = new ValidDailySchedules();

        int[][] dailySchedulesOfFullTimeEmployees = v.dailySchedulesOfFullTimeEmployees;

        int[][] workPeriodsSchedulesOfFullTimeEmployees
                = new int[v.length() * this.shiftWorkPerDay][this.workPeriodsPerSchedule];

        // Cette fonction sera a ameliorer avec des sous-fonctions, car elle n'est pas tres explicite.
        for (int scheduleNumber = 0; scheduleNumber < v.length(); scheduleNumber++) {
            for (int day = 0; day < this.daysPerSchedule; day++) {
                for (int shiftNumber = 0; shiftNumber < this.shiftWorkPerDay; shiftNumber++) {
                    if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 0) {
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 0] = 1;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 1] = 1;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 2] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 3] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 4] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 5] = 0;
                    } else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 1) {
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 0] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 1] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 2] = 1;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 3] = 1;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 4] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 5] = 0;
                    } else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 1 && shiftNumber == 2) {
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 0] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 1] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 2] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 3] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 4] = 1;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 5] = 1;
                    } else if (dailySchedulesOfFullTimeEmployees[scheduleNumber][day] == 0) {
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 0] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 1] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 2] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 3] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 4] = 0;
                        workPeriodsSchedulesOfFullTimeEmployees[scheduleNumber * this.shiftWorkPerDay + shiftNumber][day * this.workPeriodsPerDay + 5] = 0;
                    }
                }
            }
        }

        // Creation des tuples a partir du tableau pour creer les 3 types de quart de travail (nuit, jour soir).
        this.enumerationWorkPeriodsSchedulesOfFullTimeEmployees
                = new Tuples(workPeriodsSchedulesOfFullTimeEmployees, true);
    }

    private void setValidPartTimeEmployeeShiftTuples() {
        this.ValidPartTimeEmployeeShiftTuples = new ValidPartTimeEmployeeShift().makeTuples();
    }


    // A implementer plus tard si l'on veut travailler avec des fichiers texte
    public ParametersInitialSchedules(String fileName) {

//		String line = null;
//		try {
//            FileReader fileReader = 
//                new FileReader(fileName);
//
//            BufferedReader bufferedReader = 
//                new BufferedReader(fileReader);
//
//            if((line = bufferedReader.readLine()) != null) {
//            	String[] arrayLine= line.split("\\s+");
//            	PARAMETRES_HORAIRE[0] = Integer.parseInt(arrayLine[0]);
//            	PARAMETRES_HORAIRE[1] = Integer.parseInt(arrayLine[1]);
//            	PARAMETRES_HORAIRE[2] = Integer.parseInt(arrayLine[2]);
//            	PARAMETRES_HORAIRE[3] = Integer.parseInt(arrayLine[3]);
//            }   
//            if((line = bufferedReader.readLine()) != null) {
//            	String[] arrayLine= line.split("\\s+");
//            	for (int i = 0 ; i < p ; i++) {
//            		NBR_EMPLOYES_REQUIS[i] = Integer.parseInt(arrayLine[i]);
//            	}
//            }  
//            if((line = bufferedReader.readLine()) != null) {
//            	String[] arrayLine= line.split("\\s+");
//            	for (int i = 0 ; i < p ; i++) {
//            		NBR_EMPLOYES_SOUHAITES[i] = Integer.parseInt(arrayLine[i]);
//            	}
//            } 
//            bufferedReader.close();         
//        }
//        catch(FileNotFoundException ex) {
//            System.out.println(
//                "Unable to open file '" + 
//                fileName + "'");                
//        }
//        catch(IOException ex) {
//            System.out.println(
//                "Error reading file '" 
//                + fileName + "'");                  
//        }
    }

}
