package InitialSchedules;

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

public class ParametersInitialSchedules {
   
    //General Parameters
    private final int shiftWorkPerDay = 3;
    private final int daysPerSchedule = 14;
    private final int hoursPerWorkPeriod = 4;
    private final int workingHoursPaidAtRegularHourlyRatePerSchedule = 80;
    private final int workingHoursPaidAtRegularHourlyRatePerShiftWork = 8;
    

    //PartTime Employees Parameters
    private final int fixedCostOfPartTimeEmployeesPerSchedule = 50;
    private final int regularHourlyRateOfPartTimeEmployees = 12;
    private final int overtimeHourlyRateOfPartTimeEmployees = 17;
    private final int minWorkingHoursOfPartTimeEmployeesPerSchedule = 32;
    private final int maxWorkingHoursOfPartTimeEmployeesPerSchedule = 64;
    private final int maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork = 12;
    private final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees = 12;
    
    //FullTime Employees Parameters
    private final int fixedCostOfFullTimeEmployeesPerSchedule = 50;
    private final int regularHourlyRateOfFullTimeEmployees = 10;
    private final int overtimeHourlyRateOfFullTimeEmployees = 15;
    private final int workingHoursOfFullTimeEmployeesPerSchedule = 80;
    private final int maxWorkingHoursOfFullTimeEmployeesPerSchedule = 120;
    private final int maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork = 12;
    private final int minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees = 12;

    private int[] requiredWorkforce;
    int NbFullTimeSolutions;
    int NbPartTimeSolutions;
    Tuples enumerationWorkPeriodsSchedulesOfFullTimeEmployees;
    Tuples enumerationWorkPeriodsSchedulesOfPartTimeEmployees;
    private Tuples ValidPartTimeEmployeeShiftTuples;

    public ParametersInitialSchedules() {

        this.setRequiredWorkforce();
        this.enumerationWorkPeriodsSchedulesOfFullTimeEmployees = GenerationPossibleEmployeeSchedules.setWorkPeriodsSchedulesOfFullTimeEmployees(
                                                                            shiftWorkPerDay, getWorkPeriodsPerSchedule(), getWorkPeriodPerDay(), daysPerSchedule);
        this.enumerationWorkPeriodsSchedulesOfPartTimeEmployees = GenerationPossibleEmployeeSchedules.setWorkPeriodsSchedulesOfPartTimeEmployees(
                                                                            getWorkPeriodsPerSchedule(), getWorkPeriodPerDay(), daysPerSchedule);
        this.ValidPartTimeEmployeeShiftTuples = new ValidPartTimeEmployeeShift().makeTuples();

    }

    private void setRequiredWorkforce() {

        this.requiredWorkforce = new int[this.daysPerSchedule * this.getWorkPeriodPerDay()];
        int[] dailyRequiredWorkforce = new int[]{2, 2, 4, 4, 3, 3};
        for (int day = 0; day < this.daysPerSchedule; day++) {
            System.arraycopy(dailyRequiredWorkforce, 0, this.requiredWorkforce, day * this.getWorkPeriodPerDay(), this.getWorkPeriodPerDay());
        }
    }
    
    public void adjustRequiredWorkforce( FullTimeEmployeeScheduleArray fullTimeSchedule) {
        
        for (int workPeriod = 0 ; workPeriod < this.getWorkPeriodsPerSchedule() ; workPeriod++) {
            this.requiredWorkforce[workPeriod] -= fullTimeSchedule.getEmployeesWorkingPerWorkPeriod(workPeriod);
        }
        
    }
    
    public int getTotalWorkedPeriodsInSchedule() {
        int totalWorkedPeriodsInSchedule = 0;
        for (int workPeriod = 0 ; workPeriod < this.getWorkPeriodsPerSchedule() ; workPeriod++) {
            totalWorkedPeriodsInSchedule += this.requiredWorkforce[workPeriod];
        }
        return totalWorkedPeriodsInSchedule;
    }

    public int getRequiredWorkForce(int workPeriod) {
        return this.requiredWorkforce[workPeriod];
    }

    public void setRequiredWorkforce(int[] vector) {
        for(int workPeriod=0;workPeriod<vector.length;workPeriod++) {
            this.requiredWorkforce[workPeriod] = vector[workPeriod];
        }
    }
    
    public int getDaysPerSchedule() {
        return daysPerSchedule;
    }
    
    public int getWorkPeriodsPerSchedule() {
        return this.getWorkPeriodPerDay() * this.daysPerSchedule;
    }
    
    public int getWorkPeriodPerDay() {
        return 24 / this.hoursPerWorkPeriod;
    }
    
    public int  getFixedCostOfPartTimeEmployeesPerSchedule() {
        return this.fixedCostOfPartTimeEmployeesPerSchedule;
    }
    
    public int  getFixedCostOfFullTimeEmployeesPerSchedule() {
        return this.fixedCostOfFullTimeEmployeesPerSchedule;
    }

    public int getWorkingPeriodsPaidAtRegularHourlyRatePerSchedule () {
        return workingHoursPaidAtRegularHourlyRatePerSchedule / this.hoursPerWorkPeriod;
    }

    public int getWorkingPeriodsPaidAtRegularHourlyRatePerShiftWork () {
        return workingHoursPaidAtRegularHourlyRatePerShiftWork / this.hoursPerWorkPeriod;
    }

    public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtRegularHourlyRate () {
        return regularHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod;
    }

    public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtRegularHourlyRate () {
        return regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
    }
    
    public int getMinimumWorkingPeriodCost () {
        return regularHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
    }

    public int getWorkingPeriodCostOfPartTimeEmployeesPaidAtOvertimeHourlyRate () {
        return overtimeHourlyRateOfPartTimeEmployees * this.hoursPerWorkPeriod;
    }

    public int getWorkingPeriodCostOfFullTimeEmployeesPaidAtOvertimeHourlyRate () {
        return overtimeHourlyRateOfFullTimeEmployees * this.hoursPerWorkPeriod;
    }

    public int getMaxConsecutiveWorkingPeriodsOfFullTimeEmployeesPerShiftWork () {
        return maxConsecutiveWorkingHoursOfFullTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod;
    }

    public int getMaxConsecutiveWorkingPeriodsOfPartTimeEmployeesPerShiftWork () {
        return maxConsecutiveWorkingHoursOfPartTimeEmployeesPerShiftWork / this.hoursPerWorkPeriod;
    }

    public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfPartTimeEmployees () {
        return minConsecutiveNonWorkingHoursBetweenShiftWorksOfPartTimeEmployees / this.hoursPerWorkPeriod;
    }

    public int getMinConsecutiveNonWorkingPeriodsBetweenShiftWorksOfFullTimeEmployees () {
        return minConsecutiveNonWorkingHoursBetweenShiftWorksOfFullTimeEmployees / this.hoursPerWorkPeriod;
    }

    public int getMaxWorkingPeriodsOfPartTimeEmployeesPerSchedule () {
        return this.maxWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
    }

    public int getMaxWorkingPeriodsOfFullTimeEmployeesPerSchedule () {
        return this.maxWorkingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
    }

    public int getMinWorkingPeriodsOfPartTimeEmployeesPerSchedule () {
        return this.minWorkingHoursOfPartTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;

    }

    public int getWorkingPeriodsOfFullTimeEmployeesPerSchedule () {
        return this.workingHoursOfFullTimeEmployeesPerSchedule / this.hoursPerWorkPeriod;
    }

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

}
