classdef SCDclass_taskcontainer
    % This class is a container class
    % for tasks object, a task object is a 
    % generic object customizable for
    % specifying tasks at init and 
    % terminate phases
    
    properties                            
        numtasks            % number of configured tasks
        tasks               % tasks list
        modeltoexecute      % model name whose tasks will be executed 'all' for all
        modeltogenerate     % model name whose tasks will be generate 'all' for all, TODO: check overlap with the previous
    end
    
    methods
        function obj = SCDclass_taskcontainer()
            % contructor, empty container
            obj.numtasks=0;                        
        end
        
        function obj = addtask(obj, task)
            % Adds a parameter object
            if obj.numtasks==0
                obj.tasks=task;
            else
                obj.tasks=[obj.tasks; task];
            end 
            obj.numtasks=obj.numtasks+1;
        end
        
        function obj = printtasks(obj)
            % prints the parameters object list
            if obj.numtasks>0
               for ii=1:obj.numtasks
                  obj.tasks(ii).printinfo();
               end
            end
        end

        function obj = exectasksoninit(obj, shot)
            % execs the init method of all configurted task
            if obj.numtasks>0
               for ii=1:obj.numtasks
                  if(strcmp(obj.modeltoexecute,'all'))
                    obj.tasks(ii).init(shot);
                  else
                    if(strcmp(obj.modeltoexecute,obj.tasks(ii).getmodelname))
                       obj.tasks(ii).init(shot);
                    end
                  end
               end
            end
        end
        
        function obj = exectasksonterm(obj, shot)
            % execs the term method of all configurted task
            if obj.numtasks>0
               for ii=1:obj.numtasks
                  if(strcmp(obj.modeltoexecute,'all'))
                    obj.tasks(ii).term(shot);
                  else
                    if(strcmp(obj.modeltoexecute,obj.tasks(ii).modelname))
                       obj.tasks(ii).term(shot);
                    end
                  end                   
               end
            end
        end        
        
        function obj = bindlasttask(obj, modelname, datadictionary)
            if obj.numtasks>0   
               obj.tasks(end)=obj.tasks(end).setmodelname(modelname);
               obj.tasks(end)=obj.tasks(end).setdatadictionary(datadictionary);
            end        
        end
        
            
        function obj = importtaskobjects(obj, source)
            % parameters import

            desttasktargets={};
            if obj.numtasks>0             
                for ii=1:obj.numtasks
                    desttasktargets{end+1}=obj.tasks(ii).getid;
                end
            end
                           
            numtaskstoimport = source.numtasks;
            taskstoimport = source.tasks;
            
            if numtaskstoimport>0
                for ii=1:numtaskstoimport
                    if ~ismember(taskstoimport(ii).getid, desttasktargets)
                        obj=obj.addtask(taskstoimport(ii));
                    else
                        warning('SCDclass_taskcontainer:importtaskobjects','A task object with target ''%s'' is already present in the dest. expcode, skipping!',taskstoimport(ii).getid);
                    end
                end
            end
                       
        end
        
        function printMARTe2taskconfig(obj, shot)
          switch obj.modeltogenerate
            case 'all'
              iorder = getParamsServerTreeOrder(obj);  % order entries following mdsserver, mdstree order
              prevServer = ''; % init 
              
              % Header for MDS for loader
              loaderStr = sprintf('\n\n+MDSTasks = {\n Class=MDSObjLoader\n Shot=%d\n',shot);
              fprintf("%s",loaderStr);
         
              for ii=1:obj.numtasks
                mytask = obj.tasks(iorder(ii));

                currentServer = mytask.getMDSserver;

                % generate header for MDSsource if necessary
                if ~strcmp(currentServer,prevServer) %if a new server needs to be opened
                  if ii~=1, fprintf(' }\n'), end % close bracket for previous one
                  % print new source header
                  fprintf("%s\n",mytask.genMARTe2MDSsourcestr); 
                end
                prevServer = currentServer;
                
                % generate data source entry
                str = mytask.genMARTe2entry(shot);
                fprintf("  %s\n",str);
              end
              fprintf(" }\n}\n\n");

            otherwise
              for ii=1:obj.numparams
                if(strcmp(obj.modeltogenerate,obj.tasks(ii).getmodelname))
                  str=obj.tasks(ii).genMARTe2entry(shot);
                  fprintf("  %s\n",str);
                end
              end
          end
        end

        function iorder = getParamsServerTreeOrder(obj)
          % find server-tree order of parameters
          mdsservertree = cell(numel(obj.tasks),2);
          for ii=1:numel(obj.tasks)
            mdsservertree{ii,1} = obj.tasks(ii).getMDSserver;
            mdsservertree{ii,2} = obj.tasks(ii).getMDStree;
          end
          [~,iorder] = sortrows(mdsservertree);
        end

                      
    end
end

