function sltpda_execute_loops(model)
% SLTPDA_EXECUTE_LOOPS runs all the loops in the input data-analysis pipeline.
% If not loops are present, then the pipeline is executed once.
% 
% Usage: sltpda_execute_loops(model)
% 
% M Hewitson 12-06-07
% 
% $Id: sltpda_execute_loops.m,v 1.2 2007/06/13 08:47:28 hewitson Exp $
% 

% Make sure the model is open
open_system(model);

if sltpda_verify_model(model)
  
  global sltpda_loop_plotTitle;
  
  % parse model file
  cmds  = sltpda_parse_model(model);
  save 'cmds.mat' cmds
  ncmds = length(cmds);
  
  % get loops 
  loops = sltpda_buildloops(model)
  save 'loops.mat' loops
  nloops = length(loops);
  % how many loops switched on
  non = 0;
  for j=1:nloops
    if strcmp(loops(j).on, 'on')
      non = non + 1;
    end
  end
  % go through each loop
  if nloops > 0 && non > 0
    
    % convert the loops to a set of substitution commands
    subs = loops2subs(loops);
    
    % Now run levels
    l1idx = find([subs.level] == 1);
    l2idx = find([subs.level] == 2);
    l3idx = find([subs.level] == 3);

    for l1=l1idx
      if isempty(l2idx)
        ll = [l1];
        % command substitution
        runLoop2(cmds, subs(ll))        
      else
        for l2=l2idx
          if isempty(l3idx)
            ll = [l1 l2];
            % command substitution
            runLoop2(cmds, subs(ll))            
          else
            for l3=l3idx
              ll = [l1 l2 l3];
              
              

              
              % command substitution
              runLoop2(cmds, subs(ll))
            end
          end
        end
      end
    end

%     for l=1:nloops
%       % - for each loop we need to adjust the parameters of the model
%       % - look for the command to modify then set the parameter
%       loop = loops(l);
%       if strcmp(loop.on, 'on')
%         values = str2num(loop.values);
%         if isempty(values)
%           values = loop.values;
%         end
%         nvals = length(values);
%         for v=1:nvals
%           % set sltpda_loop_plotTitle
%           if isnumeric(values(v))
%             sltpda_loop_plotTitle = ['loop_' loop.key '_' num2str(values(v))];
%           else
%             sltpda_loop_plotTitle = ['loop_' loop.key '_' values(v)];
%           end
%           runLoop(cmds, str2num(loop.handle), loop.key, values(v));
%         end
%       end
%     end
  else
    runLoop2(cmds, []);
%     runLoop(cmds, [], [], []);
  end
end


%--------------------------------------------------------------------------
% Run a loop around a set of commands
% 
function runLoop2(cmds, subs)


global sltpda_loop_plotTitle;

% evaluate each command
% - here we can set the waitbar caption to display the current
% - parameter name and value
disp('-----------------------------------------------------------')
sltpda_loop_plotTitle = [];
h  = waitbar(0,'Executing pipeline...');
nc = length(cmds);
for j=1:nc
  cmd = cmds(j);
  if isempty(subs)
    sidx = [];
  else
    sidx = find(cmd.handle == [subs.handle]);
  end
  for k=1:length(sidx)
%     cmd
    key = subs(sidx(k)).key;
    val = subs(sidx(k)).value;
    if isnumeric(val)
      valstr = mat2str(val);
    else
      valstr = char(val);
    end
    sltpda_loop_plotTitle = [sltpda_loop_plotTitle ' / ' key ':' valstr];
    if iscell(val)
      val = char(val);
    end
    disp('^^^ performing parameter substitution.');
    pl = cmd.plist;
    pl = set(pl, key, val);
    params = string(pl);
    newcmd = sltpda_buildCmd(cmd.ins, cmd.outs, params, cmd.fcn);
    cmd.cmd = newcmd;
  end
  disp(['== executing: ' cmd.cmd]);
  eval(cmd.cmd);
  waitbar(j/nc,h)
end
delete(h);

disp('-----------------------------------------------------------')

%--------------------------------------------------------------------------
% convert loops to substitutions
function subs = loops2subs(loops)

% make empty substitutions; one for each allowed level
subs = [];
% subs(1).handle = [];
% subs(1).level  = 1;
% subs(1).key    = '';
% subs(1).value  = [];
% subs(2).handle = [];
% subs(2).level  = 2;
% subs(2).key    = '';
% subs(2).value  = [];
% subs(3).handle = [];
% subs(3).level  = 3;
% subs(3).key    = '';
% subs(3).value  = [];


k = length(subs)+1;
for j=1:length(loops)
  
  loop = loops(j);
  ll   = loop.level;
  
  % go through each value for this loop
  vals = loop.values;
  if ~isempty(str2num(vals))
    vals = str2num(vals);
  else
    vals = str2cells(vals);
  end

  for v=1:length(vals)
    eval(sprintf('subs(%d).handle = str2double(loop.handle);', k));
    eval(sprintf('subs(%d).level  = str2num(loop.level);', k));
    eval(sprintf('subs(%d).key    = loop.key;', k));
    eval(sprintf('subs(%d).value  = vals(v);', k));

    k = k + 1;
  end
end

%--------------------------------------------------------------------------
% Run a loop around a set of commands
% 
function runLoop(cmds, handle, key, val)

% evaluate each command
% - here we can set the waitbar caption to display the current
% - parameter name and value
h  = waitbar(0,'Executing pipeline...');
nc = length(cmds);
for j=1:nc
  cmd = cmds(j);
  hval = (1-handle/cmd.handle);
%   if hval  < 1e-10
  if handle == cmd.handle
    cmd
    disp('^^^ performing parameter substitution.');
    pl = cmd.plist;
    pl = set(pl, key, val);
    params = string(pl);
    newcmd = sltpda_buildCmd(cmd.ins, cmd.outs, params, cmd.fcn);
    cmd.cmd = newcmd;
  end
  disp(['== executing: ' cmd.cmd]);
  eval(cmd.cmd);
  waitbar(j/nc,h)
end
delete(h);
