function EMR = TRI_CY_sim_1C1S(patients, slots, surgery_begin_time, surgery_end_time, counting_days)
% TRI_sim_1C1S - first come first served simulation
% On input:
%     lambda (float): arrival rate of ED urgent cases
%     T (float): max time for simulation period
%     priority_prob (5x1 vector): probabilities of urgency (low to high)
%     slots (5x2 vector): time bin for priority
%     d_mu (float): mean duration of surgery
%     d_var (float): variance of duration of surgery
%     type(int): the generate type
% On output:
%     EMR (nx6 array): Emergency Health Records
%       col 1: arrival time
%       col 2: priority (5 slots)
%       col 3: surgery duration
%       col 4: surgery start time
%       col 5: surgery end time
%       col 6: -1 early; 0 on time; 1 late
%       col 7: If patient surgery late, how much time is lated, 0 otherwise
% Call:
%      
%      prob_list = [0.05; 0.6; 0.35];
%      patients = TRI_CY_arrivals(2,24,prob_list,1,1,1);
%      TB = [0,3; 3,12; 12,24];
%      EMR_FCFS = TRI_CY_sim_1C1S(patients,TB,0,24,50);
%
% Author:
%     Chengyu Yang
%     UU
%     Fall 2023
%

arrivals = patients;
patient_number = size(arrivals, 1);
EMR = zeros(patient_number, 7);
EMR(:, 1:3) = arrivals;

free_interval = [];

for i = 1:counting_days
    
    time_begin = surgery_begin_time + (i - 1) * 24;
    time_end = surgery_end_time + (i - 1) * 24;
    free_time = time_end - time_begin;
    new_line = [time_begin, time_end, free_time];
    free_interval = [free_interval; new_line];

end

if surgery_begin_time == 0 && surgery_end_time == 24
    
    free_time = counting_days * 24;
    free_interval = [0, free_time, free_time];

end

for i = 1:patient_number

    % get the data for every patient as temp data 
    temp_surgery_duration = EMR(i, 3);
    temp_arrive_time = EMR(i, 1);
    temp_priority = EMR(i, 2);
    
    % get the max delay and min delay
    temp_max_delay = slots(temp_priority, 2);
    temp_min_delay = slots(temp_priority, 1);
    
    % generate the minimun "in time" and maximum "in time"
    temp_intime_begin = temp_arrive_time + temp_min_delay;
    temp_intime_end = temp_arrive_time + temp_max_delay;

    best_begin = inf;
    best_line = inf;

    for a = 1:size(free_interval,1)
            
        % just do check for inverval free time is bigger than 
        % surgery duration.
        if free_interval(a, 3) >= temp_surgery_duration
                
            earlest_start = free_interval(a, 1);
            % the latest start time if the surgery happen in this time
            % interval
            latest_start = free_interval(a, 2) - temp_surgery_duration;

            if earlest_start <= temp_arrive_time && latest_start >= temp_arrive_time
                best_begin = temp_arrive_time;
                best_line = a;
                break
            elseif earlest_start > temp_arrive_time
                best_begin = earlest_start;
                best_line = a;
                break
            end

        end
            
    end
    
    % separate free interval
    new_line = [best_begin + temp_surgery_duration, ...
                free_interval(best_line, 2)];
    new_line_free = new_line(2) - new_line(1);

    if new_line_free ~= 0
        new_line = [new_line, new_line_free];
        free_interval = [free_interval(1:best_line, :); new_line; ...
                         free_interval(best_line+1:end, :)];
    end

    free_interval(best_line, 2) = best_begin;
    best_line_free = best_begin - free_interval(best_line,1);
    free_interval(best_line, 3) = best_line_free;

    if best_line_free == 0
        free_interval(best_line, :) = [];
    end
    
    % generate EMR by begin and end time get before
    EMR(i, 4) = best_begin;
    EMR(i, 5) = best_begin + temp_surgery_duration;

    if best_begin < temp_intime_begin
        EMR(i, 6) = -1;
    elseif best_begin > temp_intime_end
        EMR(i, 6) = 1;
        EMR(i, 7) = best_begin - temp_intime_end;
    else
        EMR(i, 6) = 0;
    end

end

% number_of_total_delay = sum(EMR(:, 6) == 1);
% average_delay_time = sum(EMR(:, 7)) / patient_number;
% disp("patient number of delay: " + number_of_total_delay)
% disp("average delay time: " + average_delay_time)