function cmds = getBlockCommands(blocks)

% GETBLOCKCOMMANDS get a set of commands from a set of sLTPDA blocks.
%
% M Hewitson 27-03-07
%


disp('   + compiling block list');

cmds = [];

for j=1:length(blocks)
  b         = blocks(j);
  blocktype = get(b, 'BlockType');
  maskType = get(b, 'MaskType');
  name      = get(b, 'Name');
  if ~strcmp(name, 'variable')
    parent    = get(b, 'Parent');
    name = [parent '_' name];
    name = sltpda_reduceVarName(name);

    if ~strcmp(blocktype, 'Outport') && ~strcmp(blocktype, 'Inport') && ~strcmp(maskType, 'loop')
      fcn       = getFcnName(b);
      if ~isempty(fcn)

        % Get my inputs and outputs
        [inames, onames] = getIOnames(get(b, 'PortHandles'), name);

        % Get my parameters
        [params, pl] = getParameters(b);

        % Form command
        %       cmd = buildCmd(inames, onames, params, fcn);
        cmd = sltpda_buildCmd(inames, onames, params, fcn);

        % store info
        info.fcn      = fcn;
        info.params   = params;
        info.plist    = pl;
        info.ins      = inames;
        info.outs     = onames;
        info.outsUsed = [];
        info.cmd      = cmd;
        info.name     = get(b, 'Name');
        info.handle   = get(b, 'Handle');
        info.ranges   = [];

        cmds = [cmds info];
      end
    end
  end
end


%--------------------------------------------------------------------------
% Get parameters from block mask
% 
% MaskPromptString, MaskVariables, MaskValueString
% 
function [params, pl] = getParameters(block)

params = [];
pl = plist();
try
  maskType = get(block, 'MaskType');  
end

if ~isempty(maskType)
  switch maskType

    case 'ltpda_tfe'
      [params, pl] = get_ltpda_tfe_params(block);
    case 'ltpda_pwelch'
      [params, pl] = get_ltpda_pwelch_params(block);
    case 'plot'
      [params, pl] = get_plot_params(block);
    case 'ao'
      [params, pl]  = get_ao_params(block);
    case 'filter'
      [params, pl] = get_filter_params(block);
    case 'get'
      [params, pl] = get_get_params(block);
    case 'rdivide'
      [params, pl] = get_mrdivide_params(block);
    case 'minus'
      [params, pl] = get_minus_params(block);
    case 'plus'
      [params, pl] = get_plus_params(block);
    case 'times'
      [params, pl] = get_mtimes_params(block);
    case 'sqrt'
      [params, pl] = get_sqrt_params(block);
    case 'abs'
      [params, pl] = get_abs_params(block);
    case 'split'
      [params, pl] = get_split_params(block);
    case 'demux'
      [params, pl] = get_demux_params(block);
    case 'ltpda_timedomainfit'
      [params, pl] = get_ltpda_timedomainfit_params(block);
    case 'ltpda_lincom'
      [params, pl] = get_ltpda_lincom_params(block);
    case 'ltpda_polydetrend'
      [params, pl] = get_ltpda_polydetrend_params(block);
    case 'ltpda_lpsd'
      [params, pl] = get_ltpda_lpsd_params(block);
    case 'save'
      [params, pl] = get_save_params(block);
    case 'resample'
      [params, pl] = get_resample_params(block);
    case 'pzmresp'
      [params, pl] = get_pzmresp_params(block);
    case 'convert'
      [params, pl] = get_convert_params(block);
    case 'param'
      [params, pl] = get_param_params(block);
    case 'iparam'
      [params, pl] = get_iparam_params(block);
    case 'specwin'
      [params, pl] = get_specwin_params(block);
    case 'plist'
      [params, pl] = get_plist_params(block);
    case 'display'
      pl = [];
      params = '';
    case 'pole'
      [params, pl] = get_pole_params(block);
    case 'zero'
      [params, pl] = get_zero_params(block);
    case 'pzmodel'
      [params, pl] = get_pzmodel_params(block);
    case 'resp'
      [params, pl] = get_resp_params(block);
    case 'miir'
      [params, pl] = get_miir_params(block);
    case 'iirResp'
      [params, pl] = get_iirResp_params(block);
    otherwise
      warning(['### unknown mask type ' maskType]);
  end
else
  pl = plist();
  params = [];
end

%--------------------------------------------------------------------------
% Get parameters for abs block.
% 
function [params, pl]  = get_abs_params(block)

% build output
pl = plist();
params = '';

%--------------------------------------------------------------------------
% Get parameters for iirResp block.
% 
function [params, pl]  = get_iirResp_params(block)

f1    = get(block, 'f1');
f2    = get(block, 'f2');
nf    = get(block, 'nf');

if isempty(f1)
  f1 = '[]';
end
if isempty(f2)
  f2 = '[]';
end
if isempty(nf)
  nf = '[]';
end
% build output
pl = plist( [param('f1', eval(f1)) param('f2', eval(f2)) param('nf', eval(nf))] );
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for miir block.
% 
function [params, pl]  = get_miir_params(block)

fs    = get(block, 'fs');

if isempty(fs)
  fs = '[]';
end
% build output
pl = plist( param('fs', eval(fs)) );
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for resp block.
% 
function [params, pl]  = get_resp_params(block)

f1    = get(block, 'f1');
f2    = get(block, 'f2');
nf    = get(block, 'nf');
scale = get(block, 'scale');

if isempty(f1)
  f1 = '[]';
end
if isempty(f2)
  f2 = '[]';
end
if isempty(nf)
  nf = '[]';
end
% build output
pl = plist( [param('f1', eval(f1)) param('f2', eval(f2)) param('nf', eval(nf)) param('scale', scale)] );
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for pzmodel block.
% 
function [params, pl]  = get_pzmodel_params(block)

% build output
pl = plist();
params = '';

%--------------------------------------------------------------------------
% Get parameters for zero block.
% 
function [params, pl]  = get_zero_params(block)

f = get(block, 'zerof');
q = get(block, 'zeroQ');
if isempty(q)
  q = '0';
end

% build output
pl = plist( [param('f', eval(f)) param('q', eval(q))] );
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for pole block.
% 
function [params, pl]  = get_pole_params(block)

f = get(block, 'polef');
q = get(block, 'poleQ');
if isempty(q)
  q = '0';
end

% build output
pl = plist( [param('f', eval(f)) param('q', eval(q))] );
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for plist block.
% 
function [params, pl]  = get_plist_params(block)

% build output
pl = plist();
params = '';

%--------------------------------------------------------------------------
% Get parameters for iparam block.
% 
function [params, pl]  = get_iparam_params(block)

key = get(block, 'key');


% build output
pl = plist(param(key, -1));
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for specwin block.
% 
function [params, pl]  = get_specwin_params(block)

name = get(block, 'wname');
N    = get(block, 'wlen');
psll = get(block, 'psll');

% check what value is


% build output
pl = plist([param('Name', name) param('N', eval(N)) param('PSLL', eval(psll))]);
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for param block.
% 
function [params, pl]  = get_param_params(block)

key = get(block, 'key');
val = get(block, 'val');


% build output
pl = plist([param('key', key) param('val', eval(val))]);
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for convert block.
% 
function [params, pl]  = get_convert_params(block)

pl = plist();
params = '';

%--------------------------------------------------------------------------
% Get parameters for pzmresp block.
% 
function [params, pl]  = get_pzmresp_params(block)

f1 = get(block, 'f1');
f2 = get(block, 'f2');
nf = get(block, 'nf');
pzm = get(block, 'pzm');

pl = plist();
if ~isempty(f1)
  pl = append(pl, param('f1', str2double(f1)));
end
if ~isempty(f2)
  pl = append(pl, param('f2', str2double(f2)));
end
if ~isempty(nf)
  pl = append(pl, param('nf', str2double(nf)));
end
if ~isempty(pzm)
  pl = append(pl, param('pzmodel', eval(pzm)));
else
  error('### pole/zero constructor is empty.');
end
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for resample block.
% 
function [params, pl]  = get_resample_params(block)

fsout = get(block, 'fsout');
pl = plist();
pl = append(pl, param('fsout', str2double(fsout)));
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for save block.
% 
function [params, pl]  = get_save_params(block)

fname = get(block, 'fname');
pl = plist();
pl = append(pl, param('filename', fname));
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for ltpda_lpsd block.
% 
function [params, pl] = get_ltpda_lpsd_params(block)

Kdes = str2double(get(block, 'Kdes'));
Kmin = str2double(get(block, 'Kmin'));
Jdes = str2double(get(block, 'Jdes'));
Win = get(block, 'win');
nolap   = str2double(get(block, 'olap'));
psll    = str2double(get(block, 'psll'));

params = [];
pl = plist(param('Kdes', Kdes));
pl = append(pl, param('Kmin', Kmin));
pl = append(pl, param('Jdes', Jdes));

nfft = 10;
switch Win
  case 'Kaiser'
    if psll <=0 
      error('### ltpda_lpsd block: please specify PSLL for Kaiser window.')
    end
    p = sprintf('specwin(''Kaiser'', %f, %f)', nfft, psll);
  case 'Hanning'
    p = sprintf('specwin(''Hanning'', %f)', nfft);
  otherwise
    error('### ltpda_lpsd block: Unknown window name.');
end

pl = append(pl, param('win', eval(p)));
if nolap > 0
  pl = append(pl, param('Olap', nolap));
end

params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for ltpda_polydetrend block.
% 
function [params, pl] = get_ltpda_polydetrend_params(block)

N = get(block, 'degree');

params = [];
pl = plist(param('N', N));
params = string(pl);



%--------------------------------------------------------------------------
% Get parameters for ltpda_lincom block.
% 
function [params, pl] = get_ltpda_lincom_params(block)


coeffs = get(block, 'coeffs');

params = [];
pl = plist(param('coeffs', coeffs));
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for ltpda_timedomainfit block.
% 
function [params, pl] = get_ltpda_timedomainfit_params(block)

params = [];
pl = plist();


%--------------------------------------------------------------------------
% Get parameters for demux block.
% 
function [params, pl] = get_demux_params(block)

params = [];
pl = plist();

%--------------------------------------------------------------------------
% Get parameters for sqrt block.
% 
function [params, pl] = get_split_params(block)

method = get(block, 'method');
splits = get(block, 'splits');

pl = plist();
pl = append(pl, param(method, str2num(splits) ));
params = string(pl);


%--------------------------------------------------------------------------
% Get parameters for sqrt block.
% 
function [params, pl] = get_sqrt_params(block)

pl = plist();
params = [];

%--------------------------------------------------------------------------
% Get parameters for mrdivide block.
% 
function [params, pl] = get_mrdivide_params(block)

pl = plist();
params = [];

%--------------------------------------------------------------------------
% Get parameters for mtimes block.
% 
function [params, pl] = get_mtimes_params(block)

pl = plist();
params = [];

%--------------------------------------------------------------------------
% Get parameters for minus block.
% 
function [params, pl] = get_minus_params(block)

pl = plist();
params = [];

%--------------------------------------------------------------------------
% Get parameters for plus block.
% 
function [params, pl] = get_plus_params(block)

pl = plist();
params = [];

%--------------------------------------------------------------------------
% Get parameters for get block.
% 
function [params, pl] = get_get_params(block)

pl = plist();
params = ['''' get(block, 'param') ''''];

%--------------------------------------------------------------------------
% Get parameters for filter block.
% 
function [params, pl] = get_filter_params(block)


% first we try for a standard filter
fname = [];
ftype = [];
try 
  ftype  = get(block, 'ftype');
  fgain  = get(block, 'fgain');
  ffc    = get(block, 'ffc');
  forder = get(block, 'forder');
  % we design for 4*ffc and adjust later when
  % we know the fs of the input data
  fc     = str2num(ffc);
  ffs    = 4*fc(end);
catch 
  try
    fname = get(block, 'fname');
  catch 
  end
end


% start plist
pl = plist();
if isempty(fname)
  
  % if not a standard filter, then a pole/zero filter
  if isempty(ftype)
    
    miirstr = get(block, 'miirstr');
    eval(['pzm = ' miirstr ';']);
    pl      = plist(param('filter', miir(plist(param('pzmodel', pzm)))));
    params  = string(pl);
    
  % else a standard filter  
  else
    
    % build standard filter
    if strcmp(ftype, 'bandpass') || strcmp(ftype, 'bandreject')
      if length(str2num(ffc)) ~= 2
        error('### supply upper and lower frequency for bandpass and bandreject filters.');
      end
    end

    fpl = plist();
    fpl = append(fpl, param('type', ftype));
    fpl = append(fpl, param('gain', str2double(fgain)));
    %   fpl = append(fpl, param('fs', (ffs)));
    fpl = append(fpl, param('fc', [str2num(ffc)]));
    fpl = append(fpl, param('order', [str2num(forder)]));

    pl = plist(param('filter', miir(fpl)));
    params = string(pl);
  end
else  
  pl = plist(param('filter', miir(fname)));
  params = string(pl);
end

%--------------------------------------------------------------------------
% Get parameters for ao block.
% 
function [params, pl]  = get_ao_params(block)

fname    = [];
vals     = [];
fcn      = [];
tsfcn    = [];
waveform = [];
try fname    = get(block, 'fname'); end;
try vals     = get(block, 'vals'); end;
try fcn      = get(block, 'fcn'); end;
try tsfcn    = get(block, 'tsfcn'); end;
try waveform = get(block, 'waveform'); end;

% execute 
if ~isempty(fname)
  pl = plist();
  pl = append(pl, param('filename', fname));
  params = string(pl);
elseif ~isempty(vals)
  pl = plist(param('vals', str2num(vals)));
  params = string(pl);
elseif ~isempty(fcn)
  pl = plist(param('fcn', fcn));
  params = string(pl);
elseif ~isempty(tsfcn)
  nsecs = sltpda_getvar(block, 'nsecs');
  fs    = sltpda_getvar(block, 'fs');
  pl = plist();
  pl = append(pl, param('nsecs', nsecs));
  pl = append(pl, param('fs', fs));
  pl = append(pl, param('tsfcn', tsfcn));
  params = string(pl);
elseif ~isempty(waveform)
  
  switch waveform
    %------------ Sine Wave
    case 'sine wave'
      freq = get(block, 'freq');
      phi  = get(block, 'phi');
      tsfcn = sprintf('sin(2*pi*%f*t + %f*pi/180)', eval(freq), eval(phi));
    %------------ Noise
    case 'noise'
      ntype = get(block, 'ntype');
      switch ntype
        case 'Normal'
          tsfcn = 'randn(size(t))';
        case 'Uniform'
          tsfcn = 'rand(size(t))';
      end
    %------------ Chirp
    case 'chirp'
      f0  = get(block, 'chirp_f0');
      fe  = get(block, 'chirp_fe');
      te  = get(block, 'chirp_te');
      tsfcn = sprintf('chirp(t,%f,%f,%f)', eval(f0), eval(fe), eval(te))
    %------------ Gaussian pulse
    case 'Gaussian pulse'
      fc  = get(block, 'gp_f0');
      bw  = get(block, 'gp_bw');
      tsfcn = sprintf('gauspuls(t,%f,%f)', eval(fc), eval(bw));
    case 'Square wave'
      freq = get(block, 'freq');
      duty = get(block, 'square_duty');
      tsfcn = sprintf('square(2*pi*%f*t,%f)', eval(freq), eval(duty));
    case 'Sawtooth'
      freq  = get(block, 'freq');
      width = get(block, 'sawtooth_width');
      tsfcn = sprintf('sawtooth(2*pi*%f*t,%f)', eval(freq), eval(width));
  end
  pl = plist();
  pl = append(pl, param('tsfcn', tsfcn));
  params = string(pl);
else  
  error('### unknown parameter method for AO construction.');
end

%--------------------------------------------------------------------------
% Get parameters for plot block.
% 
function [params, pl] = get_plot_params(block)

pl = plist();

xscale = get(block, 'xscale');
yscale = get(block, 'yscale');

params = [];


%--------------------------------------------------------------------------
% Get parameters for ltpda_pwelch block.
% 
function [params, pl] = get_ltpda_pwelch_params(block)

pl = plist();

nfft    = get(block, 'Nfft');
nolap   = get(block, 'Nolap');

if isempty(nfft)
  nfft = 0;
else
  nfft = str2double(nfft);
end
if isempty(nolap)
  nolap = 0;
else
  nolap = str2double(nolap);
end

pl = plist();
if nfft > 0
  pl = append(pl, param('Nfft', nfft));
end
if nolap > 0
  pl = append(pl, param('Nolap', nolap));
end
params = string(pl);

%--------------------------------------------------------------------------
% Get parameters for ltpda_tfe block.
% 
function [params, pl] = get_ltpda_tfe_params(block)

winname = get(block, 'win');
nfft    = get(block, 'nfft');
nolap   = get(block, 'nolap');
psll    = get(block, 'psll');

if isempty(nfft)
  nfft = 0;
else
  nfft = str2double(nfft);
end
if isempty(nolap)
  nolap = 0;
else
  nolap = str2double(nolap);
end
if isempty(psll)
  psll = 0;
else
  psll = str2double(psll);
end

switch winname
  case 'Kaiser'
    if psll <=0 
      error('### ltpda_tfe block: please specify PSLL for Kaiser window.')
    end
    p = sprintf('specwin(''Kaiser'', %f, %f)', nfft, psll);
  case 'Hanning'
    p = sprintf('specwin(''Hanning'', %f)', nfft);
  otherwise
    error('### ltpda_tfe block: Unknown window name.');
end

pl = plist();
pl = append(pl, param('Nfft', nfft));
pl = append(pl, param('Win', eval(p)));
if nolap > 0
  pl = append(pl, param('Nolap', nolap));
end
params = string(pl);

%--------------------------------------------------------------------------
% Build command string
% 
function cmd = buildCmd(inames, onames, params, fcn)

cmd = '';

% add outputs
if ~isempty(onames)
  cmd = [cmd '['];
  for k=1:length(onames)
    cmd = [cmd onames{k} ','];
  end
  cmd = [cmd(1:end-1) ']'];
  cmd = [cmd ' = '];
end

% add fcn name
cmd = [cmd fcn];

% add inputs
cmd = [cmd '('];
if ~isempty(inames)
  for k=1:length(inames)
    cmd = [cmd inames{k} ','];
  end
end

% add parameters
if ~isempty(params)
  cmd = [cmd params];
else
  cmd = cmd(1:end-1);
end

cmd = [cmd ')'];
cmd = [cmd ';'];

%--------------------------------------------------------------------------
% get function name from block handle
function fcn = getFcnName(b)

blocktype = get(b, 'blocktype');
if ~strcmp(blocktype, 'Outport') && ~ strcmp(blocktype, 'Inport')
  name     = get(b, 'Name');
  masktype = get(b, 'MaskType');

  if isempty(masktype) && ~strcmp(blocktype, 'SubSystem')
    fcn = name;
  else
    fcn = masktype;
  end
  
  % Some overrides to this
  switch blocktype
    case 'Sum'
      fcn = 'plus';
    case 'Mux'
      fcn = 'mux';
    case 'Demux';
      fcn = 'demux';      
  end
  
  % Some function replacements
  switch fcn
    case 'plot'
      fcn = 'figure,plot';
    case 'filter'
      fcn = get(b, 'method');
    case 'convert'
      fcn = get(b, 'fcn');
    case 'iparam'
      fcn = 'param';
  end
  fcn = sltpda_fixvar(fcn);
end

%--------------------------------------------------------------------------
function [inames, onames] = getIOnames(myports, name)

% Get my inputs
inames = [];

ins = myports.Inport;
% get name of each input
for k=1:length(ins)
  ip = ins(k);
  lineState = get(ip, 'Line');
  pn = get(ip, 'PortNumber');
  if lineState == -1
    inames = [inames cellstr('[]')];
  else
    pstr = strrep([name '_in_' num2str(pn)], ' ', '_');
    pstr = sltpda_fixvar(pstr);
    inames = [inames cellstr(pstr)];
  end
end

% Get my outputs
onames = [];
outs = myports.Outport;
% get name of each output
for k=1:length(outs)
  op = outs(k);
  pn = get(op, 'PortNumber');
  pstr = strrep([name '_out_' num2str(pn)], ' ', '_');
  pstr = sltpda_fixvar(pstr);
  onames = [onames cellstr(pstr)];
end


