% FILTERBANK constructor for filterbank class.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DESCRIPTION: FILTERBANK constructor for filterbank class.
%
% CONSTRUCTOR:
%
%       fb = filterbank()                - creates an empty filterbank object
%       fb = filterbank(filters)         - construct from an array of filters
%       fb = filterbank(filters, type)   - construct from an array of
%                                          filters and the bank type
%
% <a href="matlab:utils.helper.displayMethodInfo('filterbank', 'filterbank')">Parameters Description</a>
%
% VERSION:     $Id: filterbank.m,v 1.31 2011/08/15 13:40:18 hewitson Exp $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

classdef filterbank < ltpda_uoh
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Property definition                            %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  %---------- Public (read/write) Properties  ----------
  properties
    
  end
  
  %---------- Protected read-only Properties ----------
  properties (SetAccess = protected)
    filters = []; % Filters of the bank
    type    = ''; % Type of the bank
  end
  
  %---------- Private Properties ----------
  properties (GetAccess = protected, SetAccess = protected)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                          Check property setting                           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                                Constructor                                %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods
    function obj = filterbank(varargin)
      
      import utils.const.*
      utils.helper.msg(msg.OMNAME, 'running %s/%s', mfilename('class'), mfilename);
      
      % Collect all filterbank objects
      [banks, invars, rest] = utils.helper.collect_objects(varargin(:), 'filterbank');
      
      if isempty(rest) && ~isempty(banks)
        % Do copy constructor and return
        utils.helper.msg(msg.OPROC1, 'copy constructor');
        obj = copy(banks, 1);
        for kk=1:numel(obj)
          obj(kk).addHistory(filterbank.getInfo('filterbank', 'None'), [], [], obj(kk).hist);
        end
        return
      end
      
      switch nargin
        case 0
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%   no input   %%%%%%%%%%%%%%%%%%%%%%%%%%%*
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          utils.helper.msg(msg.OPROC1, 'empty constructor');
          obj.addHistory(filterbank.getInfo('filterbank', 'None'), plist(), [], []);
          
        case 1
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%   One input   %%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          
          if ischar(varargin{1})
            %%%%%%%%%%   pzm = filterbank('foo.mat')   %%%%%%%%%%
            %%%%%%%%%%   pzm = filterbank('foo.xml')   %%%%%%%%%%
            utils.helper.msg(msg.OPROC1, 'constructing from file %s', varargin{1});
            obj = fromFile(obj, varargin{1});
          elseif isa(varargin{1}, 'miir') || isa(varargin{1}, 'mfir')
            
            obj = obj.fromFilters(plist('filters', varargin{1}));
            
          elseif isstruct(varargin{1})
            %%%%%%%%%%   mdl = filterbank(struct)   %%%%%%%%%%
            utils.helper.msg(msg.OPROC1, 'constructing from struct');
            obj = obj.fromStruct(varargin{1});
            
          elseif isa(varargin{1}, 'plist')
            %%%%%%%%%%  mdl = filterbank(plist-object)   %%%%%%%%%%
            
            pl = varargin{1};
            
            if pl.isparam('filters')
              utils.helper.msg(msg.OPROC1, 'constructing from filters');
              obj = obj.fromFilters(pl);
            elseif pl.isparam('filename')
              %%%%%%%%%%  f = filterbank('foo.mat')   %%%%%%%%%%
              %%%%%%%%%%  f = filterbank('foo.xml')   %%%%%%%%%%
              utils.helper.msg(msg.OPROC1, 'constructing from file %s', varargin{1});
              obj = fromFile(obj, pl);
              
            elseif pl.isparam('hostname') || pl.isparam('conn')
              utils.helper.msg(msg.OPROC1, 'constructing from repository %s', pl.find('hostname'));
              obj = obj.fromRepository(pl);
              
            elseif pl.isparam('built-in')
              utils.helper.msg(msg.OPROC1, 'constructing from built-in model');
              obj = fromModel(obj, pl);
              
            else
              obj.setObjectProperties(pl);
              obj.addHistory(filterbank.getInfo('filterbank', 'None'), pl, [], []);
            end
            
          else
            error('### Unknown single argument constructor.');
          end
          
        case 2
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%   two input   %%%%%%%%%%%%%%%%%%%%%%%%%%%
          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
          if (isa(varargin{1}, 'database') || isa(varargin{1}, 'mpipeline.repository.RepositoryConnection')) && isnumeric(varargin{2})
            %%%%%%%%%%  mdl = filterbank(<database-object>, [IDs])   %%%%%%%%%%
            obj = obj.fromRepository(plist('conn', varargin{1}, 'id', varargin{2}));
            
          elseif isa(varargin{1}, 'filterbank') && isa(varargin{2}, 'plist') && isempty(varargin{2}.params)
            %%%%%%%%%%  f = filterbank(filterbank, <empty-plist>)   %%%%%%%%%%
            obj = filterbank(varargin{1});
            
          elseif isa(varargin{1}, 'ltpda_filter') && ischar(varargin{2})
            %%%%%%%%%%  f = filterbank(filter-object, 'parallel')   %%%%%%%%%%
            
            obj = obj.fromFilters(plist('filters', varargin{1}, 'type', varargin{2}));
            
          elseif isa(varargin{1}, 'ltpda_filter') && isa(varargin{2}, 'plist')
            %%%%%%%%%%  f = filterbank(filter-object, plist-object)   %%%%%%%%%%
            
            obj = obj.fromFilters(combine(plist('filters', varargin{1}), varargin{2}));
            
          elseif isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl') && ...
              isa(varargin{2}, 'history')
            %%%%%%%%%%   obj = filterbank(DOM node, history-objects)   %%%%%%%%%%
            obj = fromDom(obj, varargin{1}, varargin{2});
            
          elseif isa(varargin{1}, 'ltpda_uoh') && isa(varargin{2}, 'plist')
            %%%%%%%%%%%   filterbank(<ltpda_uoh>-object, plist-object)   %%%%%%%%%%
            % always recreate from plist
            
            % If we are trying to load from file, and the file exists, do
            % that. Otherwise, copy the input object.
            if varargin{2}.isparam('filename')
              if exist(fullfile('.', find(varargin{2}, 'filename')), 'file')==2
                obj = filterbank(varargin{2});
              else
                obj = filterbank(varargin{1});
              end
            else
              obj = filterbank(varargin{2});
            end
          elseif isa(varargin{1}, 'ltpda_filter') && isa(varargin{2}, 'ltpda_filter')
            obj = obj.fromFilters(plist('filters', [varargin{:}]));
          else
            error('### Unknown 2 argument constructor.');
          end
          
        otherwise
          [filts, invars, rest] = utils.helper.collect_objects(varargin, 'ltpda_filter');
          
          if numel(filts) > 0
            obj = obj.fromFilters(plist('filters', filts));
          else
            [mdls, invars, rest] = utils.helper.collect_objects(varargin, 'filterbank');
            
            %%% Do we have a list of filterbanks as input
            if ~isempty(mdls) && isempty(rest)
              obj = filterbank(mdls);
            else
              error('### Unknown number of arguments.');
            end
          end
      end
      
    end % End constructor
    
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                             Methods (protected)                           %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods (Access = protected)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Methods (static)                               %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods (Static)
    
    function mdls = getBuiltInModels(varargin)
      mdls = ltpda_uo.getBuiltInModels('filterbank');
    end
    
    function out = VEROUT()
      out = '$Id: filterbank.m,v 1.31 2011/08/15 13:40:18 hewitson Exp $';
    end
    
    function ii = getInfo(varargin)
      ii = utils.helper.generic_getInfo(varargin{:}, 'filterbank');
    end
    
    function out = SETS()
      out = [SETS@ltpda_uoh, {'From Filters'}];
    end
    
    
    function plout = getDefaultPlist(set)
      persistent pl;
      persistent lastset;
      if exist('pl', 'var')==0 || isempty(pl) || ~strcmp(lastset, set)
        pl = filterbank.buildplist(set);
        lastset = set;
      end
      plout = pl;
    end
    
    function out = buildplist(set)
      
      if ~utils.helper.ismember(lower(filterbank.SETS), lower(set))
        error('### Unknown set [%s]', set);
      end
      
      out = plist();
      out = filterbank.addGlobalKeys(out);
      out = buildplist@ltpda_uoh(out, set);
      
      switch lower(set)
        case 'from filters'
          % Filters
          p = param({'filters','The array of MFIR or MIIR filter objects.'}, paramValue.EMPTY_DOUBLE);
          out.append(p);
          
          % Type
          p = param({'type','The type of filter bank (parallel or serial).'}, {1, {'parallel', 'serial'}, paramValue.OPTIONAL});
          out.append(p);
      end
    end % function out = getDefaultPlist(varargin)
    
    function obj = initObjectWithSize(n,m)
      obj = filterbank.newarray([n m]);
    end
    
  end % End static methods
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                         Methods (static, private)                         %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static, Access=private)
  end % End static, private methods
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                         Methods (static, hidden)                          %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  methods (Static = true, Hidden = true)
    varargout = loadobj(varargin)
    varargout = update_struct(varargin);
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                             Methods (public)                              %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods
    varargout = char(varargin)
    varargout = display(varargin)
    varargout = copy(varargin)
    varargout = resp(varargin)
    
    varargout = setIunits(varargin)
    varargout = setOunits(varargin)
  end
  
  methods (Hidden = true)
    varargout = attachToDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                            Methods (protected)                            %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods (Access = protected)
    varargout = fromStruct(varargin)
    varargout = fromDom(varargin)
  end
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %                           Methods (private)                               %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  methods (Access = private)
    % Constructors
    varargout = fromFilters(varargin)
  end
  
end % End classdef

