function ClusterControl(arg,opt,projectnamecell)
    %function ClusterControl(arg,opt,projectnamecell)
    %
    %Use GUI that allows one to setup growth projects on the cluster
    %Run them
    %Retrieve the results and clear up by deleting the intermediate files
    %
    %CONFIGURATION for running projects that are not the snapdragon
    %Find the line calling VMSReport and change as illustrated below.
    %
    %Usage
    %
    %1) At the beginning of the session, start ClusterControl and press the
    %svn update button - this ensures that the DArT_Toolshed on the cluster is
    %up to date. (To install the DArT_Toolshed in the firstplace, use WinSCP.
    %
    %2) use SilentGFtbox to prepare an experiment, e.g.
    %
    %SilentGFtbox('Name','NewFig4test2','dt',1,'Stages',[2,5,7],'Use','Cluster')
    %
    %Having set up the experiment(s) this program will send the project and the
    %commands required to run it (them) on the cluster. 
    %Finally, it will keep a note of the program that will 
    %get the results back from the cluster.
    %
    %Not only does ClusterControl keep a list of experiments, but it also
    %has buttons to enable you to check the processing queue, your directories
    %on the cluster.
    %
    %To forcibly stop the automatic collection of results type
    %
    %ti=timerfind; % finds all the timers
    %stop(ti); % this stops all the timers
    %delete(ti); % and deletes them all
    %
    %J.Andrew Bangham, 2008
%     global ClusterControl_fig
    if nargin<3
        projectnamecell={};
    end
    if nargin<1
        RegisterDeregisterTool('Exists','ClusterControl');
        data=initialise;
        ClusterControl_fig=data.ClusterControl_fig;
        % Add ClusterControl handle to any other DArT_ToolHandles
        [ToolExists,ClusterControl_fig]=RegisterDeregisterTool(...
            'Set','ClusterControl','Handle',ClusterControl_fig);
        % setup a clean exit when closing window
        set(ClusterControl_fig,'CloseRequestFcn',[mfilename,'(''Quit'',0);']);

        guidata(ClusterControl_fig,data);

        data=ClusterBufferIO(data,'r');
        v=get(data.handles.Outstandingexperiments,'Value');
        s=get(data.handles.Outstandingexperiments,'String');
        if strcmp(s,'Outstanding experiments')
            set(data.handles.svnupdate,'Enable','on');
        end
        %guidata(ClusterControl_fig,data);
    else
        [ToolExists,ClusterControl_fig]=RegisterDeregisterTool('Get','ClusterControl');
        data=guidata(ClusterControl_fig);
        if ~strcmpi(arg,'quit')
            if isempty(projectnamecell) % i.e. only when ui has been used
                set(gcf,'Pointer','watch');
                c=get(gco,'BackgroundColor');
                set(gco,'BackgroundColor','r');
                drawnow
            end
            switch lower(arg)
                case 'makepngs'
                    data=MakePngs(data,opt);
                case 'getlogs'
                    data=GetLogs(data,opt);
                case 'gettimedresults'
                    try
                    if opt==0
                        if ~isvalid(data.handles.timerhandle)
                            data.handles.timerhandle=timer;
                        end
                        data=timecontrol(data,1);
                        TasksExecuted=get(data.handles.timerhandle,'TasksExecuted');
                        TasksToExecute=get(data.handles.timerhandle,'TasksToExecute');
                        set(data.handles.Counter,'String',sprintf('%3d/%3d gets',TasksExecuted,TasksToExecute));
                        set(data.handles.NextTime,'String',...
                            datestr(datenum(datestr(clock))+data.timer_interval/(60*60)/24,'HH:MM:SS'));
                    else
                        disp('gettimedresults')
                        TasksExecuted=get(data.handles.timerhandle,'TasksExecuted');
                        TasksToExecute=get(data.handles.timerhandle,'TasksToExecute');
                        set(data.handles.Counter,'String',sprintf('%3d/%3d gets',TasksExecuted,TasksToExecute));
                        set(data.handles.NextTime,'String',...
                            datestr(datenum(datestr(clock))+data.timer_interval/(60*60)/24,'HH:MM:SS'));
                        get(data.handles.timerhandle)
                        data=GetResults(data,opt);
                        data=MakePngs(data,opt);
                    end
                    catch
                        disp('Abandon data collection tidy up by removing handle to ClusterControl');
                        set(0,'userdata',[]);
                    end
                case 'getresults'
                    data=GetResults(data,opt);
                case 'help'
                    data=ClusterControl_Help(data,opt);
                case 'button'
                    data=button(data,opt);
                case 'stackpop'
                    data=StackPop(data,opt,projectnamecell);
                case 'install'
                    ClusterSVN('Install');
                case 'stop'
                    c='r';
                case 'timecontrol'
                    data=timecontrol(data,opt);
            end
            if exist('ClusterControl_fig')==1
                if ishandle(ClusterControl_fig)
                    guidata(ClusterControl_fig,data);
                end
            end
            if isempty(projectnamecell) % i.e. only when ui has been used
                set(gcf,'Pointer','arrow');
                set(gco,'BackgroundColor',[0.9882    0.9961    0.7216]);%c);
            end
        else
            RegisterDeregisterTool('Delete','ClusterControl');
            stop(data.handles.timerhandle);
            data=timecontrol(data,false);
            delete(ClusterControl_fig);
%             delete(data.handles.timerhandle);
            delete(timerfind);
        end
    end    
end

function  data=timecontrol(data,opt)
    if opt
        %start timer
        if isvalid(data.handles.timerhandle)
            set(data.handles.timerhandle, 'ExecutionMode', 'FixedRate',...
                ...'StartFcn',[mfilename,'(''GetTimedResults'',1);'],...
                'TimerFcn',[mfilename,'(''GetTimedResults'',1);'],...
                'StopFcn',[mfilename,'(''timecontrol'',0);'],...
                'Period', data.timer_interval, ... %60*60*2,...
                'TasksToExecute',data.duration_of_looking); %48); % two days worth
            start(data.handles.timerhandle);
            periodhours=data.timer_interval/(60*60);
            if ishandle(data.handles.NextTime)
                set(data.handles.NextTime,'String',...
                    datestr(datenum(datestr(clock))+data.timer_interval/(60*60)/24,'HH:MM:SS'));
            end
        else
            set(data.handles.NextTime,'String','Off');
        end
    else
        %stop timer
        stop(data.handles.timerhandle);
        set(data.handles.NextTime,'String','Off');
    end
end

function data=initialise
    cwp=pwd;
    [pathstr, name]=fileparts(cwp);
    if ~strcmp(name,'clusterstuff')
        error(...
            'Please create a directory called ''clusterstuff'', move all projects into it, and move into it');
    end
    ClusterControl_fig = openfig(mfilename, 'reuse');
    set(ClusterControl_fig,'Color',[252,254,184]/255);
    handles = guihandles(ClusterControl_fig);
    set(handles.Clear,'callback',[mfilename,'(''Button'',1);'],'Enable','on');
    set(handles.deletesh,'callback',[mfilename,'(''Button'',2);'],'Enable','on');
    set(handles.deleteproject,'callback',[mfilename,'(''Button'',3);'],'Enable','off');
    set(handles.svnupdate,'callback',[mfilename,'(''Button'',4);'],'Enable','off');
    set(handles.qstat,'callback',[mfilename,'(''Button'',5);']);
    set(handles.deleteprojectexperiments,'callback',[mfilename,'(''Button'',6);'],'Enable','off');
    set(handles.dirproject,'callback',[mfilename,'(''Button'',7);'],'Enable','off');
    set(handles.dir,'callback',[mfilename,'(''Button'',8);']);
    set(handles.help,'callback',[mfilename,'(''ClusterControl_Help'',0);'],'Enable','off');
    set(handles.Exit,'callback',[mfilename,'(''Quit'',0);']);
    set(handles.Install,'callback',[mfilename,'(''Install'',0);']);
    set(handles.GetResults,'callback',[mfilename,'(''GetResults'',0);'],'Enable','off');
    set(handles.GetAllResults,'callback',[mfilename,'(''GetTimedResults'',0);'],'Enable','on');
    set(handles.GetLog,'callback',[mfilename,'(''GetLogs'',0);'],'Enable','off');
    set(handles.GetAllLogs,'callback',[mfilename,'(''GetLogs'',1);'],'Enable','off');
    set(handles.MakeProjectPngs,'callback',[mfilename,'(''MakePngs'',0);'],'Enable','off');
    set(handles.MakeAllPngs,'callback',[mfilename,'(''MakePngs'',1);'],'Enable','off','Visible','off');
    set(handles.Outstandingexperiments,'callback',[mfilename,'(''StackPop'',''Select'');']);
    set(handles.Outstandingexperiments,'callback',[mfilename,'(''StackPop'',''Select'');']);
    set(handles.Stop,'callback',[mfilename,'(''Stop'',0);'],'Value',0);
    set(handles.StopClock,'callback',[mfilename,'(''timecontrol'',false);']);
    s=get(handles.Outstandingexperiments,'String');
    if ~iscell(s)
        set(handles.Outstandingexperiments,'String',{s});
    else
        set(handles.Outstandingexperiments,'String',s);
    end
    set(handles.CurrentProject,'Title','SilentGFtbox automatically adds projects');

    data.handles=handles;
    data.CurrentProjectName='';
    data.bkc=get(handles.Stop,'Backgroundcolor');
    data.handles.timerhandle=timer;
    data.duration_of_looking=60; %events
    data.timer_interval=15*60;%60*60*2; %5*60;% 60*60*2; %seconds
    data.ClusterControl_fig=ClusterControl_fig;
end

function data=MakePngs(data,opt)
    if 0 % debug 1
        disp('testing MakePngs');
    else
        disp('running MakePngs');
        s=get(data.handles.Outstandingexperiments,'String');
        ind=get(data.handles.Outstandingexperiments,'Value');
        if opt==0
            disp(sprintf('Retrieving results for one file %s',s{ind}))
            namelist{1}=s{ind};
        else
            disp(sprintf('Retrieving results for several files'))
            for i=1:length(s)
                namelist{i}=s{i};
                disp(sprintf('%s',namelist{i}));
            end
        end
        fprintf(1,'Assemble list of results to be pictured\n ');
        for i=1:length(namelist)
            fprintf(1,'%s, ',namelist{i});
        end
        disp('');

        for i=1:length(namelist)
            ProjectInstance=namelist{i};
            ProjectInstance=ProjectInstance(1:end-3);
            ProjectName=ProjectInstance(1:end-4);
            disp(sprintf('Plotting data in %s',fullfile(ProjectName,'movies',ProjectInstance,'meshes','*')))
            disp('will take some time');
            VMSreport('Project',ProjectName,'Experiment','All','flattentime',572.5,'morphogen','KPAR','SNAPFIG',true);%,'Visible',false);
%             VMSreport('Project',ProjectName,'Experiment','All','flattentime',572.5,'SNAPFIG',false);%,'Visible',false);
%             VMSreport('Project',ProjectName,'Experiment','All');% for use when not the snapdragon model
        end
    end
end

function data=GetLogs(data,opt)
    if 0 % testing
        disp('testing GetLogs');
    else
        s=get(data.handles.Outstandingexperiments,'String');
        ind=get(data.handles.Outstandingexperiments,'Value');
        if opt==0
            disp(sprintf('Retrieving log for one file %s',s{ind}))
            namelist{1}=s{ind};
        else
            disp(sprintf('Retrieving logs for several files'))
            for i=1:length(s)
                namelist{i}=s{i};
                disp(sprintf('%s',namelist{i}));
            end
        end
        % open the associated file

        for i=1:length(namelist)
            file=namelist{i};
            file=[file(1:end-3),'.txt'];
            h=fopen(file);
            if h~=-1
                k=0;
                while ~feof(h)
                    k=k+1;
                    tex{k}=fgetl(h);
                end
                fclose(h);
                for j=1:length(tex)
                    bkc=get(data.handles.Stop,'BackgroundColor');
                    if bkc(1)==1
                        break
                    end
                    n=tex{j};
                    SubmissionName=[n(1:strfind(n,'.sh')+2),'.o*'];
                    commandline=n(strfind(n,'.sh')+6:end);
                    tailLogFile(SubmissionName);
                    disp('--------------------------------------------')
                    disp(sprintf('tail of %s log\n %s',SubmissionName,commandline));
                    disp('--------------------------------------------')
                    ind1=regexpi(commandline,'ExpID'',''','end');
                    tail=commandline(ind1+1:end);
                    ind2=regexpi(tail,'''');
                    ExperimentName=tail(1:ind2-5);
                    disp(sprintf('copy_experiment_results_back(''%s'',''%s'');',SubmissionName(1:end-10),ExperimentName))
                    disp(sprintf('VMSReport(''Project'',''%s'',''Experiment'',''%s'');',SubmissionName(1:end-10),ExperimentName))
                    disp('--------------------------------------------')
                end
                bkc=get(data.handles.Stop,'BackgroundColor');
%                 if bkc(1)==1
%                     break
%                 end
                disp(sprintf('copy_experiment_results_back(''%s'',''%s*''); %% to copy some experiments back',SubmissionName(1:end-10),ExperimentName(1:end-3)))
                disp(sprintf('copy_experiment_results_back(''%s''); %% to copy all experiments back',SubmissionName(1:end-10)))
                disp(sprintf('VMSReport(''Project'',''%s'',''Experiment'',''%s''); %% to print all to png files',SubmissionName(1:end-10),ExperimentName))
                disp('--------------------------------------------')
            end
        end
        set(data.handles.Stop,'BackgroundColor',data.bkc)
        set(data.handles.GetLog,'BackgroundColor',data.bkc)
        set(data.handles.GetAllLogs,'BackgroundColor',data.bkc)
    end
end

function data=GetResults(data,opt)
    if 0 % testing
        disp('testing GetResults');
    else
        
        s=get(data.handles.Outstandingexperiments,'String');
        ind=get(data.handles.Outstandingexperiments,'Value');
        if opt==0
            disp(sprintf('Retrieving results for one file %s',s{ind}))
            namelist{1}=s{ind};
        else
            disp(sprintf('Retrieving results for several files'))
            for i=1:length(s)
                namelist{i}=s{i};
                disp(sprintf('%s',namelist{i}));
            end
        end
        fprintf(1,'Getting ');
        for i=1:length(namelist)
            fprintf(1,'%s, ',namelist{i});
        end
        disp('');

        for i=1:length(namelist)
            bkc=get(data.handles.Stop,'BackgroundColor');
            if bkc(1)==1
                disp('stop 1')
                break
            end
            ProjectInstance=namelist{i};
            ProjectInstance=ProjectInstance(1:end-3);
            ProjectName=ProjectInstance(1:end-4);
            if ~(exist(fullfile(ProjectName,'movies'))==7)
                mkdir(fullfile(ProjectName,'movies'));
            end
            disp(sprintf('Getting %s*',fullfile(ProjectName,'movies',ProjectInstance)))
            disp('Moving data back will take some time');
            files_copied=copy_experiment_results_back(ProjectName,[ProjectInstance,'*'],data.handles.Stop);
            ClusterControlPOP(ProjectInstance);
        end
%         set(data.handles.Stop,'BackgroundColor',data.bkc)
%         set(data.handles.GetResults,'BackgroundColor',data.bkc)
%         set(data.handles.GetAllResults,'BackgroundColor',data.bkc)
%         bkc=get(data.handles.Stop,'BackgroundColor');
%         if bkc(1)==1
%             disp('stop 2')
%             return
%         end
    end
end

function data=AddFromClusterBuffer(data)
    h=fopen('ClusterBuffer.txt','r');
    if h~=-1
        s={};
        while ~feof(h)
            line=fgetl(h);
            s=[s,{line}];
        end
        fclose(h);
        ClusterControl('StackPop','Add',s);
    end
end

function data=ClusterBufferIO(data,option,s)
    if nargin<3
        string='';
    end
    if option=='r'
        h=fopen('ClusterBuffer.txt','r');
        if h~=-1
            s={};
            while ~feof(h)
                line=fgetl(h);
                s=[s,{line}];
            end
            fclose(h);
            ClusterControl('StackPop','Add',s);
        end
    else % option=='w'
        h=fopen('ClusterBuffer.txt','w');
        if h~=-1
            for i=1:length(s)
                fprintf(h,'%s\n',s{i});
            end
            fclose(h);
        end
    end
end

function data=StackPop(data,opt,projectnamecell)
    handles=data.handles;
    v=get(handles.Outstandingexperiments,'Value');
    s=get(handles.Outstandingexperiments,'String');
    if ~iscell(s)
        s={s};
    end
    switch lower(opt)
        case 'add'
            if strcmp(s{1},'Outstanding experiments')
                set(handles.Outstandingexperiments,'String',projectnamecell);
            else
                set(handles.Outstandingexperiments,'Value',v+1);
                s=[s;projectnamecell];
                set(handles.Outstandingexperiments,'String',s);
            end
            data.CurrentProjectName=projectnamecell{1};
            set(handles.svnupdate,'Enable','off');
            set(handles.GetResults,'Enable','on');
            set(handles.GetAllResults,'Enable','on');
            set(handles.GetAllLogs,'Enable','on');
            set(handles.GetLog,'Enable','on');
            set(handles.MakeProjectPngs,'Enable','on');
            set(handles.MakeAllPngs,'Enable','on');
            set(handles.dirproject,'Enable','on');
            set(handles.deleteprojectexperiments,'Enable','on');
            set(handles.deleteproject,'Enable','on');
        case 'select'
            data.CurrentProjectName=s{v};
        case 'pop'
            if ~isempty(projectnamecell)
                % pop by project name
                % find first occurance of projectname in s
                v=[];
                for i=1:length(s)
                    if strcmp(s{i},projectnamecell{1})
                        v=i;
                        break
                    end
                end
            end
            if ~isempty(v)   
                % pop by selecting in gui
                indx=setdiff(1:length(s),v);
                if ~isempty(indx)
                    s=s(indx);
                    data.CurrentProjectName=s{1};
                    set(handles.Outstandingexperiments,'String',s,'Value',1);
                    data=ClusterBufferIO(data,'w',s);
%                     h=fopen('ClusterBuffer.txt','w');
%                     for i=1:length(s)
%                         fprintf(h,'%s\n',s{i});
%                     end
%                     fclose(h);
                else
                    data.CurrentProjectName='';
                    s{1}='Outstanding experiments';
                    set(handles.Outstandingexperiments,'String',s);
                    set(handles.svnupdate,'Enable','on');
                    set(handles.GetResults,'Enable','off');
                    set(handles.GetAllResults,'Enable','off');
                    set(handles.GetAllLogs,'Enable','off');
                    set(handles.GetLog,'Enable','off');
                    set(handles.MakeProjectPngs,'Enable','off');
                    set(handles.MakeAllPngs,'Enable','off');
                    set(handles.dirproject,'Enable','off');
                    set(handles.deleteprojectexperiments,'Enable','off');
                    set(handles.deleteproject,'Enable','off');
                end
            end
        case 'clear'
            s={};
            s{1}='Outstanding experiments';
            set(handles.Outstandingexperiments,'String',s);
            data.CurrentProjectName='';

            if exist('ClusterBuffer.txt','file')
                delete('ClusterBuffer.txt');
            end
            set(handles.svnupdate,'Enable','on');
            set(handles.GetResults,'Enable','off');
            set(handles.GetAllResults,'Enable','off');
            set(handles.GetAllLogs,'Enable','off');
            set(handles.GetLog,'Enable','off');
            set(handles.MakeProjectPngs,'Enable','off');
            set(handles.MakeAllPngs,'Enable','off');
            set(handles.dirproject,'Enable','off');
            set(handles.deleteprojectexperiments,'Enable','off');
            set(handles.deleteproject,'Enable','off');
    end
    if isempty(data.CurrentProjectName)
        set(handles.CurrentProject,'Title','SilentGFtbox automatically adds projects');
    else
        set(handles.CurrentProject,'Title',data.CurrentProjectName);
    end
end

function data=button(data,opt)
    switch opt
        case 1
            % clear stack
            disp('Clear the list of projects')
            data=StackPop(data,'Clear');
        case 2
            % deletesh
            disp('Delete shell scripts in your cluster workspace if there are any')
            ClusterDELJOB(data.CurrentProjectName(1:end-6));
%             ClusterDELSH;
        case 3
            % deleteproject
            disp('Delete this project from your cluster workspace if it exists')
            ClusterDELPROJ(data.CurrentProjectName(1:end-7));
            data=StackPop(data,'pop',{data.CurrentProjectName});
            %canvas_snap_081203a0646.sh
        case 4
            % svnupdate
            disp('Your Cluster svn update')
            ClusterSVN;
        case 5
            % qstat
            disp('Your Cluster job queue')
            ClusterQSTAT;
        case 6
            % deleteprojectexperiments
            disp('Delete p) directories in this project')
            ClusterDELEXP(data.CurrentProjectName(1:end-6));
        case 7
            % dirproject
            disp('Directories in your cluster workspace')
            disp(data.CurrentProjectName)
            disp('--')
            if isempty(data.CurrentProjectName)
                disp('Projects are added to the list as they are submitted using SilentGFtbox')
            else
                ClusterDIR(data.CurrentProjectName(1:end-7));
            end
        case 8
            % dir
            ClusterDIR;
    end
end