% BEGIN LICENSE BLOCK
% Version: CMPL 1.1
%
% The contents of this file are subject to the Cisco-style Mozilla Public
% License Version 1.1 (the "License"); you may not use this file except
% in compliance with the License.  You may obtain a copy of the License
% at www.eclipse-clp.org/license.
% 
% Software distributed under the License is distributed on an "AS IS"
% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
% the License for the specific language governing rights and limitations
% under the License. 
% 
% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
% Portions created by the Initial Developer are
% Copyright (C) 2001 - 2006 Cisco Systems, Inc.  All Rights Reserved.
% 
% Contributor(s): Josh Singer, Parc Technologies
% 
% END LICENSE BLOCK

% ----------------------------------------------------------------------
% System:       ECLiPSe Constraint Logic Programming System
% Version:      
%
% Example program for using queues with JavaInterface module 
%
% Author:       Josh Singer, Parc Technologies Ltd. 
% ----------------------------------------------------------------------
:- lib(ic).
:- lib(ic_sets).
:- lib(lists).

:- local struct(unscheduled_task(
        name,           % atom
        index,          % integer
        start,          % integer variable
        earliest_start, % integer 
        duration,       % integer
        need,           % list of tasks
        use            % resource id (1..NRes, 0 if no resource needed)
    )).

:- local struct(scheduled_task(
        name,           % atom
        start,          % integer 
        index,          % integer
        finish,         % integer
        use             % resource id (1..NRes, 0 if no resource needed)
    )).

:- local struct(resource(
        name,           % atom
        index,          % resource id 1..NRes
        available_time   % ic_set variable
    )).

schedule_tasks(UnscheduledTaskList, ResourceList, ScheduledTaskList):-
%schedule_tasks(UnscheduledTaskList):-
        writeln('In schedule_tasks'),
        writeln('About to execute read_data predicate'),
        %read_data(UnscheduledTaskList, ResourceList),
        writeln('About to execute initializeunscheduledtaskliststarts predicate'),
        initializeunscheduledtaskliststarts(UnscheduledTaskList),
        initializeresources(ResourceList),
        writeln('About to execute scheduletasksontoresources predicate'),
        scheduletasksontoresources(UnscheduledTaskList, ResourceList, ScheduledTaskListVar, ScheduledTaskList),
        reverse(ScheduledTaskList, ReversedScheduledTaskList),
          writeln('--------------------'),
        ( foreach(ScheduledTask,ReversedScheduledTaskList)  do
            ScheduledTask = scheduled_task{Name:TaskName, Start:TaskStart, Finish:TaskFinish, index:TaskIndex, use:ResourceId},
          writeln('TaskName: '),
          writeln(TaskName),
            writeln('TaskStart: '),
            writeln(TaskStart),
            writeln('TaskFinish: '),
            writeln(TaskFinish),
            writeln('TaskIndex: '),
            writeln(TaskIndex),
            writeln('ResourceId: '),
            writeln(ResourceId),
            writeln('--------------------')
        ).
        


read_data(UnscheduledTaskList, ResourceList):-
        T1 = unscheduled_task{name:'Task 1', index:1, use:1,duration:5},
        T2 = unscheduled_task{name:'Task 2', index:2, use:1,duration:8},
        append([T1], [T2], UnscheduledTaskList),
        R1 = resource{name:'Resource 1', index:1, available_time:R1_AT},
        %ic_sets:(R1_AT::[0..100]..[0..100]),
        createIC_SET(R1_AT,1,25),
        %ic_sets:(intset(R1_AT,0,100)),
        ResourceList = [R1].

initializeunscheduledtaskliststarts(UnscheduledTaskList):-
        ( foreach(UnscheduledTask,UnscheduledTaskList) do
            UnscheduledTask = unscheduled_task{start:Start},
            ic:(Start::[0..10000])
        ).

initializeresources(ResourceList):-
        ( foreach(ResourceVar,ResourceList) do
            ResourceVar = resource{available_time:ResourceAvailableTime},
            createIC_SET(ResourceAvailableTime,1,10000)
        ).

replaceResourceAvailabeTimeSetInResourceList(ResourceList, ScheduledTask, FinalResourceAvailableTimeSet, NewResourceList):-
            writeln('In replaceResourceAvailabeTimeSetInResourceList'),
            ScheduledTask = scheduled_task{use:ResourceId},
            writeln('Updating Resource: '),
            writeln(ResourceId),
            writeln('About to delete resource from ResourceList'),
            delete(resource(Name,ResourceId,ResourceAvailableTime), ResourceList, DeletedResourceResourceList),
            writeln('After delete resource from ResourceList'),
            UpdatedResource = resource{name:Name, index:ResourceId, available_time:FinalResourceAvailableTimeSet},
            writeln('After UpdatedResource creation'),
            append([UpdatedResource], DeletedResourceResourceList, NewResourceList),
            writeln('After adding UpdatedResource to NewResourceList').
        
scheduletasksontoresources([], ResourceList, ScheduledTaskListVar, ScheduledTaskList):-
 	writeln('scheduletaskontoresource empty list'),
        append(ScheduledTaskListVar, [], ScheduledTaskList).
        % Part of program where ScheduledTaskList is created

scheduletasksontoresources([UnscheduledTask|UnscheduledTaskList], ResourceList, ScheduledTaskListVar, ScheduledTaskList):-
 	writeln('scheduletaskontoresource not empty list'),
            UnscheduledTask = unscheduled_task{name:TaskName, index:TaskIndex, use:ResourceId,duration:TaskDuration},
            scheduleTaskOntoResource(UnscheduledTask, ResourceList, TaskScheduledTimeSet, FinalResourceAvailableTimeSet),
            writeln('TaskScheduledTimeSet'),
            writeln(TaskScheduledTimeSet),
            writeln('FinalResourceAvailableTimeSet'),
            writeln(FinalResourceAvailableTimeSet),
            %Now delete the entry in the resource list and replace it
            %with the FinalResourceAvailableTimeSet
            replaceResourceAvailabeTimeSetInResourceList(ResourceList, ScheduledTask, FinalResourceAvailableTimeSet, NewResourceList),
            %Append scheduled task onto ScheduledTaskList
            writeln('Before Convert of TaskScheduledTimeSet to TaskScheduledTimeICDomSet'),

            convertIC_SET_to_IC_DOM(TaskScheduledTimeSet, TaskScheduledTimeICDomSet),
            writeln('After Convert of TaskScheduledTimeSet to TaskScheduledTimeICDomSet'),
            writeln('TaskScheduledTimeICDomSet: '),
            writeln(TaskScheduledTimeICDomSet),
            writeln('Before min calculation'),
            getIC_DOM_min(TaskScheduledTimeICDomSet, TaskStart),
            getIC_DOM_max(TaskScheduledTimeICDomSet, TaskFinish),
            getIC_DOM_min(TaskScheduledTimeICDomSet, TaskStart),
            writeln('After min calculation'),
            writeln('RealScheduledTask variables: '),
            writeln('TaskName: '),
            writeln(TaskName),
            writeln('TaskStart: '),
            writeln(TaskStart),
            writeln('TaskFinish: '),
            writeln(TaskFinish),
            writeln('TaskIndex: '),
            writeln(TaskIndex),
            writeln('ResourceId: '),
            writeln(ResourceId),
            RealScheduledTask = scheduled_task{Name:TaskName, Start:TaskStart, Finish:TaskFinish, index:TaskIndex, use:ResourceId},
            writeln('After creation of RealScheduledTask'),
            append([RealScheduledTask], ScheduledTaskListVar, AppendedScheduledTaskList),
            writeln('After appending ScheduledTask to AppendedScheduledTaskList'),

            scheduletasksontoresources(UnscheduledTaskList, NewResourceList, AppendedScheduledTaskList, ScheduledTaskList).
         

scheduleTaskOntoResource(UnscheduledTask, ResourceList, TaskScheduledTimeSet, FinalResourceAvailableTimeSet):-            
            UnscheduledTask = unscheduled_task{start:Start, duration:TaskDuration, use:ResourceId}, writeln(ResourceList),
            member(resource(Name,ResourceId,ResourceAvailableTime), ResourceList),
            writeln('ResourceAvailableTime: '),
            writeln(ResourceAvailableTime),
            writeln('Before call to intersectTaskWithResourceAvailableTime'),
            writeln('Start'),
            writeln(Start),
            writeln('TaskDuration'),
            writeln(TaskDuration),
            writeln('ResourceAvailableTime'),
            writeln(ResourceAvailableTime),
            writeln('ScheduledTaskSetTime'),
            writeln(ScheduledTaskSetTime),
            intersectTaskWithResourceAvailableTime(Initialize, Start, TaskDuration, ResourceAvailableTime, ScheduledTaskSetTime, TaskScheduledTimeSet, FinalResourceAvailableTimeSet),
            writeln('After call to intersectTaskWithResourceAvailableTime'),
            writeln('Start'),
            writeln(Start),
            writeln('TaskDuration'),
            writeln(TaskDuration),
            writeln('ResourceAvailableTime'),
            writeln(ResourceAvailableTime),
            writeln('ScheduledTaskSetTime'),
            writeln(ScheduledTaskSetTime),
            writeln('FinalScheduledTaskSet'),
            writeln(FinalScheduledTaskSet).


intersectTaskWithResourceAvailableTime(Initialize,Start, TaskDuration, ResourceAvailableTimeSet, ScheduledTaskSetTime, FinalScheduledTaskSet, FinalResourceAvailableTimeSet):-
            writeln('In intersectTaskWithResourceAvailableTime'),
            writeln('ScheduledTaskSetTime: '),
            writeln(ScheduledTaskSetTime),
            getIC_DOM_min(Start, StartMin),
            getIC_SET_min(ResourceAvailableTimeSet, ResourceAvailableTimeMin),
            (var(Initialize)->
                 writeln('Total Scheduled Time is 0'), 
                 ic_sets:(ScheduledTaskSetTime::[]..[]),
                 TotalScheduledTime is 0 
                 ;
                 writeln('Total Scheduled Time is not 0'),
                 convertIC_SET_to_IC_DOM(ScheduledTaskSetTime, ScheduledTaskICDomSet),
                 get_domain_size(ScheduledTaskICDomSet, TotalScheduledTime)
            ),
            writeln('TotalScheduledTime: '),
            writeln(TotalScheduledTime),
            TotalTimeToSchedule is TaskDuration - TotalScheduledTime,
            writeln('TotalTimeToSchedule: '),
            writeln(TotalTimeToSchedule),
            (TotalTimeToSchedule =< 0 -> 
                writeln('TotalTimeToSchedule is 0'),
                ic_sets:(union(ScheduledTaskSetTime, ScheduledTaskSetTime, FinalScheduledTaskSet)),
                ic_sets:(union(ResourceAvailableTimeSet, ResourceAvailableTimeSet, FinalResourceAvailableTimeSet))
                ;
                writeln('TotalTimeToSchedule is not 0'),
            writeln('StartMin: '),
            writeln(StartMin),
            writeln('ResourceAvailableTimeMin'),
            writeln(ResourceAvailableTimeMin),
            %if the resource available minimum value is greater than the
            %Start set minimum set the range of the task set to begin with
            %the resource available minimum value
            (ResourceAvailableTimeMin > StartMin ->writeln('in'), createIC_SET(TaskSet, ResourceAvailableTimeMin, ResourceAvailableTimeMin + TotalTimeToSchedule);writeln('out'), createIC_SET(TaskSet, StartMin, StartMin + TotalTimeToSchedule)),
            writeln('ResourceAvailableTimeSet: '),
            writeln(ResourceAvailableTimeSet),
            writeln('TaskSet: '),
            writeln(TaskSet),
            ic_sets:(intersection(TaskSet,ResourceAvailableTimeSet,  TaskAndResourceAvailableTimeIntersectionSet)),
            writeln('TaskAndResourceAvailableTimeIntersectionSet'),
            writeln(TaskAndResourceAvailableTimeIntersectionSet),
            writeln(TaskAndResourceAvailableTimeIntersectionSet),
            convertIC_SET_to_IC_DOM(TaskAndResourceAvailableTimeIntersectionSet, TaskAndResourceAvailableTimeIntersectionICDomSet),
            get_domain_size(TaskAndResourceAvailableTimeIntersectionICDomSet, TaskAndResourceAvailableTimeIntersectionSetSize), 
            RealTaskAndResourceAvailableTimeIntersectionSetSize is TaskAndResourceAvailableTimeIntersectionSetSize,
            RealTaskDuration is TaskDuration,
            writeln('RealTaskAndResourceAvailableTimeIntersectionSetSize'),
            writeln(RealTaskAndResourceAvailableTimeIntersectionSetSize),
            writeln('RealTaskDuration'),
            writeln(RealTaskDuration),
            ic_sets:(union(ScheduledTaskSetTime, TaskAndResourceAvailableTimeIntersectionSet, NewScheduledTaskSetTime)),
            ic_sets:(NewResourceAvailableTimeVar in ResourceAvailableTimeSet),
            ic:(get_domain_as_list(NewResourceAvailableTimeVar,NewResourceAvailableTimeIntegerList)),
            writeln('NewResourceAvailableTimeIntegerList'),
            writeln(NewResourceAvailableTimeIntegerList),
            ic:(NewVar::NewResourceAvailableTimeIntegerList),
            writeln('NewVar'),
            writeln(NewVar),
            getIC_SET_max(NewScheduledTaskSetTime, MaxScheduledVal),
            NewVar#>MaxScheduledVal,
            writeln('NewVar > MaxScheduledVal'),
            writeln(NewVar),
            ic:(get_domain_as_list(NewVar,ModifiedResourceAvailableTimeIntegerList)),
            ic_sets:(ModifiedResourceAvailableTimeSet::[]..ModifiedResourceAvailableTimeIntegerList),
            writeln('---------------------------------'),
            writeln('Start'),
            writeln(Start),
            writeln('TaskDuration'),
            writeln(TaskDuration),
            writeln('ModifiedResourceAvailableTimeSet'),
            writeln(ModifiedResourceAvailableTimeSet),
            writeln('NewScheduledTaskSetTime'),
            writeln(NewScheduledTaskSetTime),
            convertIC_SET_to_IC_DOM(NewScheduledTaskSetTime, NewScheduledTaskICDomSet),
            get_domain_size(NewScheduledTaskICDomSet, NewScheduledTaskICDomSetSize),
            writeln('NewScheduledTaskICDomSetSize'), 
            writeln(NewScheduledTaskICDomSetSize),
            intersectTaskWithResourceAvailableTime(1,Start, TaskDuration, ModifiedResourceAvailableTimeSet, NewScheduledTaskSetTime, FinalScheduledTaskSet, FinalResourceAvailableTimeSet)
            ).
            
            %Now we have the task set and the all time available to the resource
            %I will limit the ResourceAvailableTimeSet to the min/max of the
            %task set.  By doing this I will be able to isolate the area 
            %of the resource available time I want to schedule onto.
            
            
               
            
getIC_SET_min(Ic_set, Min):-
	    writeln('getIC_SET_min'),
            ic_sets:(Ic_setIntegerList in Ic_set),
            ic:(get_min(Ic_setIntegerList, Min)).

getIC_DOM_min(Ic_dom, Min):-
	    writeln('getIC_DOM_min'),
            ic:(get_domain_as_list(Ic_dom,Ic_domIntegerList)),
            ic:(min(Ic_domIntegerList, Min)).

getIC_SET_max(Ic_set, Max):-
	    writeln('getIC_SET_max'),
            ic_sets:(Ic_setIntegerList in Ic_set),
            ic:(get_max(Ic_setIntegerList, Max)).

getIC_DOM_max(Ic_dom, Max):-
	    writeln('getIC_DOM_max'),
            ic:(get_domain_as_list(Ic_dom,Ic_domIntegerList)),
            ic:(max(Ic_domIntegerList, Max)).

convertIC_SET_to_IC_DOM(Ic_set, Ic_dom):-
	    writeln('convertIC_SET_to_IC_DOM'),
            ic_sets:(Ic_domVar in Ic_set),
            ic:(get_domain_as_list(Ic_domVar,Ic_setIntegerList)),
            ic:(Ic_dom::Ic_setIntegerList).

convertIC_DOM_to_IC_SET(Ic_dom, Ic_set):-
	    writeln('convertIC_DOM_to_IC_SET'),
            ic:(get_domain_as_list(Ic_dom,Ic_domIntegerList)),
            ic_sets:(Ic_set::Ic_domIntegerList..Ic_domIntegerList).

createIC_SET(Ic_set,Start, End):-
            %ic_sets:(intset(Ic_set, Start, End)).
            ic:(Ic_dom::[Start..End]),
            convertIC_DOM_to_IC_SET(Ic_dom, Ic_set).
            

    
