% DOWNSAMPLE AOs containing time-series data.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: DOWNSAMPLE AOs containing time-series data. All other AOs with
%              no time-series data are skipped but appear in the output.
%              Note that no anti-aliasing filter is applied to the
%              original data!!!
% CALL:        b = downsample(a, pl)      - use plist to get parameters
%              b = downsample(a1, a2, pl) - downsample both a1 and a2;
%                                           b is then a 2x1 vector.
%
% <a href="matlab:utils.helper.displayMethodInfo('ao', 'downsample')">Parameters Description</a>
%
% EXAMPLES:   1) downsample x4; offset is set to default of 0
%
%                >> p = plist('factor',4);
%                >> b = downsample(a, p);
%
%             2) downsample x2 with 1 sample offset
%
%                >> p = plist('factor',2,'offset',1);
%                >> b = downsample(a,p);
%
%
% VERSION:     $Id: downsample.m,v 1.34 2011/07/14 05:33:18 mauro Exp $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function varargout = downsample(varargin)

  % Check if this is a call for parameters
  if utils.helper.isinfocall(varargin{:})
    varargout{1} = getInfo(varargin{3});
    return
  end

  import utils.const.*
  utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename);
  
  % Collect input variable names
  in_names = cell(size(varargin));
  for ii = 1:nargin,in_names{ii} = inputname(ii);end

  % Collect all AOs
  [as, ao_invars] = utils.helper.collect_objects(varargin(:), 'ao', in_names);
  [pl, pl_invars] = utils.helper.collect_objects(varargin(:), 'plist', in_names);

  % Decide on a deep copy or a modify
  bs = copy(as, nargout);

  % Combine plists
  pl = parse(pl, getDefaultPlist);

  % Get parameters from plist
  offset = find(pl, 'offset');
  factor = find(pl, 'factor');

  % Checking downsampling value is valid
  if isempty(factor)
    error('### Please give a plist with a parameter ''Factor''.');
  end

  % Checking downsampling value is integer
  if rem(factor, floor(factor)) ~= 0
    warning('!!! Downsample factor should be an integer. Rounding. !!!');
    factor = round(factor);
  end

  % Checking sample offset value
  if isempty(offset)
    warning('!!! No offset specified; using default of 0 samples !!!');
    offset = 0;
  end

  if factor == 0
    error('### The downsampling factor is zero. Please set a positive integer value.');
  end
  
  % Loop over input AOs
  for jj = 1:numel(bs)
    if isa(bs(jj).data, 'tsdata')
      % get samples
      ss = 1+offset;
      samples = ss:factor:length(bs(jj).data.y);
      % select samples
      bs(jj).data.setXY(bs(jj).data.getX(samples), bs(jj).data.getY(samples));
      % Set new sample rate
      bs(jj).data.setFs(bs(jj).data.fs/factor);
      % drop X vector again if we can
      bs(jj).data.collapseX;
      % set name
      bs(jj).name = sprintf('downsample(%s)', ao_invars{jj});
      % Add history
      bs(jj).addHistory(getInfo('None'), pl, ao_invars(jj), bs(jj).hist);
      % Clear the errors since they don't make sense anymore
      clearErrors(bs(jj));
    else
      warning('!!! Downsample only works on tsdata objects. Skipping AO %s', ao_invars{jj});
    end
  end

  % Set output
  varargout = utils.helper.setoutputs(nargout, bs);
end

%--------------------------------------------------------------------------
% Get Info Object
%--------------------------------------------------------------------------
function ii = getInfo(varargin)
  if nargin == 1 && strcmpi(varargin{1}, 'None')
    sets = {};
    pl   = [];
  else
    sets = {'Default'};
    pl   = getDefaultPlist;
  end
  % Build info object
  ii = minfo(mfilename, 'ao', 'ltpda', utils.const.categories.sigproc, '$Id: downsample.m,v 1.34 2011/07/14 05:33:18 mauro Exp $', sets, pl);
end

%--------------------------------------------------------------------------
% Get Default Plist
%--------------------------------------------------------------------------

function plout = getDefaultPlist()
  persistent pl;  
  if ~exist('pl', 'var') || isempty(pl)
    pl = buildplist();
  end
  plout = pl;  
end

function pl = buildplist()
  
  pl = plist();
  
  % Factor
  p = param({'factor', 'The decimation factor. Should be an integer.'}, {1, {1}, paramValue.OPTIONAL});
  pl.append(p);
  
  % Offset
  p = param({'offset', 'The sample offset used in the decimation.'}, {1, {0}, paramValue.OPTIONAL});
  pl.append(p);
  
end


