/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ScheduleUtil;

import InitialSchedules.*;
import org.chocosolver.solver.Solution;

/**
 *
 * @author frabe
 */
//Dans cette classe, toutes les fonctions sont dedoublees. On devrait faire du polymorphisme. 
public class SchedulesArray {
    public int initialScheduleSolutionNumber;
    public boolean[][] partTimeSchedules;
    public boolean[][] fullTimeSchedules;
    public int totalScheduleCost;
    protected ParametersInitialSchedules myParametersInitialSchedules;
 
    // Constructeur Copie
    protected SchedulesArray(SchedulesArray myScheduleArray) {
        
        this.myParametersInitialSchedules = myScheduleArray.myParametersInitialSchedules;
        this.partTimeSchedules = getDeepCopyEmployeesSchedules(myScheduleArray.partTimeSchedules);
        this.fullTimeSchedules = getDeepCopyEmployeesSchedules(myScheduleArray.fullTimeSchedules);
        this.initialScheduleSolutionNumber = myScheduleArray.initialScheduleSolutionNumber;
        
    }
    
    public SchedulesArray(ModelInitialSchedules m, Solution s, int scheduleNumber) {
        this.initialScheduleSolutionNumber = scheduleNumber;
        this.myParametersInitialSchedules = m.myScheduleParameters;
        Solution mySolution = s;
            
        this.partTimeSchedules = new boolean[getNumberOfPartTimeEmployees(s, m)][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
        this.fullTimeSchedules = new boolean[getNumberOfFullTimeEmployees(s, m)][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
        
        int partTimeEmployee = 0;
        for (int i = 0; i < m.maxPartTimeEmployee; i++) {
            if (isPartTimeEmployeeActive (i, s, m)) {
                for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
                    this.partTimeSchedules[partTimeEmployee][workPeriod] = mySolution.getIntVal(m.workPeriodsSchedulesOfPartTimeEmployees[i][workPeriod]) == 1;
                }
                partTimeEmployee++;
            }
        }
        
        int fullTimeEmployee = 0;
        for (int i = 0; i < m.maxFullTimeEmployee; i++) {
            if (isFullTimeEmployeeActive (i, s, m)) {
                for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
                    this.fullTimeSchedules[fullTimeEmployee][workPeriod] = mySolution.getIntVal(m.workPeriodsSchedulesOfFullTimeEmployees[i][workPeriod]) == 1;
                }
                fullTimeEmployee++;
            }
        }
        
        this.totalScheduleCost = EmployeeCostCalculator.getFullScheduleCost(this, myParametersInitialSchedules);
        assert(this.totalScheduleCost == s.getIntVal(m.totalEmployeesCost));
        
    }
        
    private int getNumberOfPartTimeEmployees( Solution s, ModelInitialSchedules m ) {
        int numberPartTimeEmployee = 0;
        for (int employee = 0; employee < m.maxPartTimeEmployee; employee++) {
            if (isPartTimeEmployeeActive (employee, s, m)) {
                numberPartTimeEmployee++;
            }
        }
        return numberPartTimeEmployee;
    }
    
    private int getNumberOfFullTimeEmployees( Solution s, ModelInitialSchedules m ) {
        int numberFullTimeEmployee = 0;
        for (int employee = 0; employee < m.maxFullTimeEmployee; employee++) {
            if (isFullTimeEmployeeActive (employee, s, m)) {
                numberFullTimeEmployee++;
            }
        }
        return numberFullTimeEmployee;
    }
    
    private boolean isPartTimeEmployeeActive ( int employee, Solution s, ModelInitialSchedules m ) {
        int workPeriod = 0;
        while (workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule()) {
            if (s.getIntVal(m.workPeriodsSchedulesOfPartTimeEmployees[employee][workPeriod]) == 1){
                return true;
            }
            workPeriod++;
        }
        return false;
    }
    
    private boolean isFullTimeEmployeeActive ( int employee, Solution s, ModelInitialSchedules m ) {
        int workPeriod = 0;
        while (workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule()) {
            if (s.getIntVal(m.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod]) == 1){
                return true;
            }
            workPeriod++;
        }
        return false;
    }
    
    protected boolean[][] getDeepCopyEmployeesSchedules(boolean[][] schedules) {
        boolean[][] copySchedules = new boolean[schedules.length][myParametersInitialSchedules.getWorkPeriodsPerSchedule()];
        for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
            for (int employee = 0; employee < schedules.length; employee++) {
                copySchedules[employee][workPeriod] = schedules[employee][workPeriod];
            }
        }
        return copySchedules;
    }
    
    protected int getEmployeesWorkingPerWorkPeriod(int workPeriod) {
        int employeesWorking = 0;
        for (int employee = 0; employee < this.getNumberPartTimeEmployee(); employee++) {
            if (this.partTimeSchedules[employee][workPeriod]) {employeesWorking += 1;}
        }
        for (int employee = 0; employee < this.getNumberFullTimeEmployee(); employee++) {
            if (this.fullTimeSchedules[employee][workPeriod]) {employeesWorking += 1;}
        }
        return employeesWorking;
    }
    
    protected int getWorkingPeriodsPerPartTimeEmployees(int employee) {
        int workingPeriodsPerPartTimeEmployees = 0;
        for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
            if (this.partTimeSchedules[employee][workPeriod]) {workingPeriodsPerPartTimeEmployees += 1;}
        }
        return workingPeriodsPerPartTimeEmployees;
    }
    
    protected int getWorkingPeriodsPerFullTimeEmployees(int employee) {
        int workingPeriodsPerFullTimeEmployees = 0;
        for (int workPeriod = 0; workPeriod < myParametersInitialSchedules.getWorkPeriodsPerSchedule(); workPeriod++) {
            if (this.fullTimeSchedules[employee][workPeriod]) {workingPeriodsPerFullTimeEmployees += 1;}
        }
        return workingPeriodsPerFullTimeEmployees;
    }
    
    public int getNumberFullTimeEmployee() {
        return this.fullTimeSchedules.length;
    }

    public int getNumberPartTimeEmployee() {
        return this.partTimeSchedules.length;
    }

    public int getWorkPeriodsPerSchedule() {
        return myParametersInitialSchedules.getWorkPeriodsPerSchedule();
    }
    
    public boolean isPartTimeEmployeeWorking(int employee, int workPeriod) {
        return partTimeSchedules[employee][workPeriod] == true;
    }
    
    public boolean isFullTimeEmployeeWorking(int employee, int workPeriod) {
        return fullTimeSchedules[employee][workPeriod] == true;
    }
    
}
