% REBUILDLIBRARY rebuilds the library on the workbench by processing the
% ltpda_versions cell-array.
% 
% CALL:  wb.rebuildLibrary
% 
% M Hewitson 11-10-08
% 
% $Id: rebuildLibrary.m,v 1.17 2011/04/28 13:26:26 hewitson Exp $
% 
function varargout = rebuildLibrary(varargin)
  % setup library
  lib = mpipeline.jltpda.LTPDAlibrary('LTPDA');
  % Get current verbose level
  prefs =  getappdata(0, 'LTPDApreferences');
  vl    = double(prefs.getDisplayPrefs.getDisplayVerboseLevel);  
  prefs.getDisplayPrefs.setDisplayVerboseLevel(java.lang.Integer(-1));
  % Add each user class
  ucls = utils.helper.ltpda_userclasses;
  
  % Add any user-class subclasses from extension modules
  searchPaths = prefs.getExtensionsPrefs.getSearchPaths;
  for kk=0:searchPaths.size-1
    % path to the new classes
    path = fullfile(char(searchPaths.get(kk)), 'classes');
    % get a list of class directories
    classdirs = utils.prog.dirscan(path, '@.*');
    for jj=1:numel(classdirs)
      parts = regexp(classdirs{jj}, '@', 'split');
      cldir = parts{end};      
      md = meta.class.fromName(cldir);
      if utils.helper.isSubclassOf(md, 'ltpda_uo')
        fprintf('+ adding user-object class %s from extension %s\n', md.Name, path);
        ucls = [ucls {md.Name}];
      end      
    end
  end
    
  cats = utils.const.categories.list;
  cats = cats(~strcmp(cats, 'Internal'));
  cats = cats(~strcmp(cats, 'GUI function'));
  warning off
  
  %% Build the infrastructure first
  for jj=1:numel(ucls)
    clcat = mpipeline.jltpda.LTPDAcategory(ucls{jj});
    lib.addCategory(clcat);
  end
  
  % Now go through and add the contents
  for jj=1:numel(ucls)
    clcat = lib.getCategoryByName(ucls{jj});
    disp(sprintf('** Building: %s', ucls{jj}));
    % add each algorithm for this class/category
    [clmethods, infos] = getPublicMethods(ucls{jj});
    % add each method to its subcategory
    for ll=1:numel(clmethods)
      ii = infos(ll);
      mthCategory = ii.mcategory;
      cat = clcat.getCategoryByName(mthCategory);
      if isempty(cat)
        if ~strcmp(mthCategory, 'Internal') && ~strcmp(mthCategory, 'GUI function')
          cat = mpipeline.jltpda.LTPDAcategory(mthCategory);
          clcat.addSubCategory(cat);
        end
      end
%       else
      if ~isempty(cat)
        disp(sprintf('  + adding method %s/%s to category %s', ucls{jj}, clmethods{ll}, char(cat.getName)))
        a = LTPDAworkbench.minfo2algo(ii);
        a.setParamsHTML(html(ii));
        cat.addAlgorithm(a);
      end
    end
  end
  warning on
  if nargin > 0
    wb = varargin{1};
    awtinvoke(wb.mp, 'setLibrary', lib);
    awtinvoke(wb.mp, 'refreshLibraryTree');  
  end
  % set verbose level again
  prefs.getDisplayPrefs.setDisplayVerboseLevel(java.lang.Integer(vl));
  if nargout > 0
    varargout{1} = lib;
  end
end


function [mths, infos] = getPublicMethods(cl)
  
  disp(sprintf('   collecting methods for %s class...', cl));
  mths = {};
  
  cms = eval(['?' cl]);
  infos = [];
  for ll=1:numel(cms.Methods)
    
    mt = cms.Methods{ll};
    if  ~mt.Static                    && ...
        ~mt.Hidden                    && ...
        strcmpi(mt.Access, 'public')  && ...
        ~strcmpi(cms.Methods{ll}.DefiningClass.Name, 'handle')
      
      % get category
      try
        cmd = sprintf('%s.getInfo(''%s'');', cl, mt.Name);
        ii = eval(cmd);        
%         disp(['    found method: ' mt.Name]);
        mths = [mths {ii.mname}];
        infos = [infos ii];
      catch
        warning('### could not get info about: %s', mt.Name);
      end      
    end
    
  end
  
  [mths,i,j] = unique(mths);
  infos = infos(i);
  
  
end

% Make an html table of the minfo object suitable for display on the GUI
% help pane.
function txt = html(ii)
  
  txt = '';
  % Table of the minfo object
  txt = [txt sprintf('      <table cellspacing="0" class="body" cellpadding="2" border="1" width="60%%">\n')];
  txt = [txt sprintf('        <thead>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <th class="categorylist" colspan="2">Some information of the method %s/%s are listed below:</th>\n', ii.mclass, ii.mname)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('        </thead>\n')];
  txt = [txt sprintf('        <tbody>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#f3f4f5">Class name</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#f3f4f5">%s</td>\n', ii.mclass)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#ffffff">Method name</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#ffffff">%s</td>\n', ii.mname)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#f3f4f5">Category</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#f3f4f5">%s</td>\n', ii.mcategory)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#ffffff">CVS Version</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#ffffff">%s</td>\n', ii.mversion)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#f3f4f5">Min input args</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#f3f4f5">%d</td>\n', ii.argsmin)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#ffffff">Max input args</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#ffffff">%d</td>\n', ii.argsmax)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#f3f4f5">Min output args</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#f3f4f5">%d</td>\n', ii.outmin)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('          <tr valign="top">\n')];
  txt = [txt sprintf('            <td width="25%%" bgcolor="#ffffff">Max output args</td>\n')];
  txt = [txt sprintf('            <td bgcolor="#ffffff">%d</td>\n', ii.outmax)];
  txt = [txt sprintf('          </tr>\n')];
  txt = [txt sprintf('        </tbody>\n')];
  txt = [txt sprintf('      </table>\n')];
  
  % Table of the sets
  for ll=1:numel(ii.sets)
    set = ii.sets{ll};
    pl  = ii.plists(ll);
    
    txt = [txt sprintf('      <table cellspacing="0" class="body" cellpadding="4" summary="" width="100%%" border="2">\n')];
    
    txt = [txt sprintf('        <thead>\n')];
    txt = [txt sprintf('        	<tr valign="top">\n')];
    txt = [txt sprintf('        		<th bgcolor="#B9C6DD" colspan="4"><h3>%s</h3></th>\n',  set)];
    txt = [txt sprintf('      	  </tr>\n')];
    txt = [txt sprintf('        	<tr valign="top">\n')];
    txt = [txt sprintf('      	  	<th width="15%%" bgcolor="#D7D7D7">Key</th>\n')];
    txt = [txt sprintf('        		<th width="25%%" bgcolor="#D7D7D7">Default Value</th>\n')];
    txt = [txt sprintf('        		<th bgcolor="#D7D7D7">Options</th>\n')];
    txt = [txt sprintf('      	  	<th bgcolor="#D7D7D7">Description</th>\n')];
    txt = [txt sprintf('        	</tr>\n')];
    txt = [txt sprintf('        </thead>\n')];
    
    
    txt = [txt sprintf('        <tbody>\n')];
    for kk=1:pl.nparams
      txt = [txt sprintf('          <tr valign="top">\n')];
      txt = [txt sprintf('            <td width="15%%" bgcolor="#F2F2F2">%s</td>\n', pl.params(kk).key)];
      ptxt = display(pl.params(kk));
      txt = [txt sprintf('            <td width="25%%" bgcolor="#F2F2F2">%s</td>\n', strtrim(strrep(ptxt{3}, 'val:', '')))];
      if numel(pl.params(kk).getOptions) > 1
        opts = pl.params(kk).getOptions;
        optlist ='<ul>';
        for oo=1:numel(opts)
          optlist = [optlist '<li><font color="#1111FF">' utils.helper.val2str(opts{oo}) '</font></li>'];
        end
        optlist = [optlist '</ul>'];        
        txt = [txt sprintf('            <td bgcolor="#F2F2F2">%s</td>\n', optlist)];
      else
        txt = [txt sprintf('            <td bgcolor="#F2F2F2"><i>none</i></td>\n')];
      end
      txt = [txt sprintf('            <td bgcolor="#F2F2F2">%s</td>\n', char(strrep(pl.params(kk).desc, '\n', '<br></br>')))];
      txt = [txt sprintf('          </tr>\n')];
      
    end
    txt = [txt sprintf('        </tbody>\n')];
    txt = [txt sprintf('      </table>\n')];

  end
end


