%MEQHELP  MEQ function helps and structure fields' usage
% MEQHELP(codename,helptype,dosave) displays help information of various
% types.
%
% codename: ('liu','fbt','fgs','fge');
% helptype: 
%   'inputs','outputs','parameters': listing of i/o/parameter names 
%   'functions': Listing of help of all functions 
%   'mex' : Listing of help of all mex files
%   'L usage': Listing of all usages of all fields in L
%   'G usage': Listing of all usages of all fields in G
%   'P usage': Listing of all usages of all fields in P
% dosave: If true, save output to a log file
%
% Variable name conventions:
% -- Name -----------------------------------------------------------------
% a:sqrt(x^2+y^2)    b:box              c:                d:
% e:j+f              f:fractional index g:Jx bf           h:
% i:                 j:0-based index    k:1-based index   l:logical index
% m:                 n:                 o:theta           p:rho
% q:                 r:radial coord     s:                t:time
% u:                 v:                 w:                x:r-rA
% y:z-zA             z:vert coord
% A:                 B:magnetic field   C:                D:
% E:                 F:flux             G:p T2/2 bf       H:matrix for FE
% I:measured current J:fitted current   K:                L:
% M:mutual           N:NL eq. state     O:domain          P:polynom coeff
% Q:FS integrals     R:resistance       S:CDE integral    T:transformation
% U:voltage          V:                 W:weighted B,M    X:measurements
% Y:weighted X       Z:fitted Y
% -- Prefix ---------------------------------------------------------------
% a:                 b:                 c:cos             d:mesh step
% e:                 f:                 g:                h:half
% i:inverse          j:                 k:                l:
% m:                 n:number           o:                p:
% q:square           r:                 s:sin             t:
% u:triu             v:                 w:                x:
% y:                 z:previous sample
% A:                 B:                 C:                D:
% E:                 F:                 G:                H:
% I:integral         J:                 K:                L:
% M:                 N:                 O:                P:
% Q:                 R:                 S:                T:
% U:                 V:                 W:                X:
% Y:                 Z:A/b for LLS fit
% -- Suffix/system --------------------------------------------------------
% 0:initial guess    1:1st mesh point   9:last mesh point
% a:coils            b:boundary         c:b-corners       d:diagnostics
% e:a+u              f:loops            g:Jy bf           h:FE
% i:t+p              j:g+dz             k:                l:limiter
% m:probes           n:interp points    o:constraints     p:(mesh in) plasma
% q:theta,rho mesh   r:f+m              s:vessel segments t:toroidal
% u:general vessel   v:vessel filaments w:coil filaments  x:mesh
% y:x-b              z:
% A:magnetic axis    B:LCFS             C:LCFS control    D:domain center
% E:                 F:                 G:g+a+u           H:hexapole points
% I:                 J:                 K:approx points   L:limiter points
% M:fit coeff matrix N:                 O:                P:plasma total
% Q:q+A              R:Br=0 / Rat-surf  S: r/a surface    T:
% U:                 V:Vs ctrl point    W:Wall gaps       X:X point
% Y:                 Z:Bz=0
%
% [+MEQ MatlabEQuilibrium Toolbox+] Swiss Plasma Center EPFL Lausanne 2022. All rights reserved.
function dfile = meqhelp(codename,helptype,dosave)
if nargin==0
  help(mfilename);
  return
end

if nargin<3
  dosave=false;
end

if contains(helptype,'usage')
  switch codename
    case {'liu','liuqe'}
      L = liu('ana',1,0);
    case {'fbt','fbte'}
      L = fbt('ana',1);
    case {'fgs'}
      L = fgs('ana',1);
    case {'fge'}
      L = fgs('ana',1);
    otherwise
      error('no help implemented yet for %s.',codename);
  end
end

% diary file
if dosave
dfile = sprintf('%s_%s_%s.txt',tempname,codename,helptype);
diary(dfile)
end

% get code file names
codem = getmnames(sprintf('%s*.m',codename));
meqm  = getmnames('meq*.m');
mexm  = getmnames('*mex*.m');

srcs = [codem,meqm,mexm];

%%
switch helptype
  case 'inputs'
    codeh = sprintf('%sx.m',codename);
    printcodehelp(codename,helptype,codeh)
  case 'outputs'
    printcodehelp('MEQ',helptype,'meqt.m')
    codeh = sprintf('%st.m',codename);
    printcodehelp(codename,helptype,codeh)
  case 'parameters'
    printcodehelp('MEQ',helptype,'meqp.m')
    codeh = sprintf('%sp.m',codename);
    printcodehelp(codename,helptype,codeh)
  case 'functions'
    for file = codem
      helpnofields(file{:})
      fprintf('\n\n')    
    end
  case 'mex'
    for file = mexm
      helpnofields(file{:});
      fprintf('\n\n')    
    end
  case 'P usage'
    for k = sort(fieldnames(L.P))'
      fprintf('\n%%%% L.P.%s\n',k{1});
      [~,s] = system(['grep -Hne "\<P\.' k{1} '\>" ' strjoin(srcs)]);
      gp(s)
    end
  case 'G usage'
    for k = sort(fieldnames(L.G))'
      fprintf('\n%%%% L.G.%s\n',k{1});
      [~,s] = system(['grep -Hne "\<G\.' k{1} '\>" ' strjoin(srcs)]);
      gp(s)
    end
  case 'L usage'
    for k = sort(fieldnames(L))'
      switch k{:}
        case {'P' 'G'}
        otherwise
          fprintf('\n%%%% L.%s\n',k{:});
          [~,s] = system(['grep -Hne L\\.' k{:} ' ' strjoin(srcs)]);
          gp(s)
      end
    end
  otherwise
    error('unknown helptype %s')
end

if dosave
diary off
fprintf('created file %s with help for %s\n',dfile,codename)
end
end

function gp(s)
fp = '';
while length(s) > 1
  [l,s] = strtok(s,newline); %#ok<*STTOK>
  [f,l] = strtok(l,':'); f = strrep(f,'/tmp/','');
  [n,l] = strtok(l,':'); l = strtrim(l(2:end)); l(56:end) = '';
  if strcmp(fp,f), f = '';
  else, fp = f; end
  fprintf('%%%12s:%5s:%s\n',f,n,l);
end
end

function names = getmnames(str)
% get names of files
dd = dir(str);
assert(~isempty(dd),'no files found matching %s',str)
for ii=1:numel(dd)
  names{ii} = dd(ii).name;
end
end


function printcodehelp(codename,helptype,codeh)
fprintf('\n\n%s %s %s %s \n\n','%%%%%% ',upper(codename), helptype, '%%%%%%%');
helpfields(codeh);
end

function helpfields(file)
% get parameter descriptions, start with % .*
   fid = fopen(file,'r');
   s = 0;
   while 1
     line = fgetl(fid);
     if ~ischar(line), break, end
     line = strtrim(line);
     if ~isempty(line)
       if line(1) == '%' && s == 0 % is a comment
         s = 1; % occurrence counter
       elseif line(1) ~= '%' && s == 1
         s = 2;
         break
       end
       if s == 1 && ~isempty(regexp(line,'%{1}\s+\.\w+', 'once')) % contains .[character]
         [remi,remj] = regexp(line,'%{1}\s+\.', 'once');
         fprintf('%s\n',line(remj+1:end)); % append line removing '% .'
       end
     elseif s == 1
       s = 2;
       break
     end
   end
   fclose(fid);
end

function helpnofields(file)
% get bare help without parameter descriptions
   fid = fopen(file,'r');
   s = 0;
   while 1
     line = fgetl(fid);
     if ~ischar(line), break, end
     line = strtrim(line);
     if ~isempty(line)
       if isequal(deblank(line),'%'); break; end
       if line(1) == '%' && s == 0 % is a comment
         s = 1; % occurrence counter
       elseif line(1) ~= '%' && s == 1
         s = 2;
         break
       end
       if s == 1 
         [~,remj] = regexp(line,'%{1}', 'once');
         fprintf('%s\n',line(remj+1:end)); % append line removing '% .'
       end
     elseif s == 1
       s = 2;
       break
     end
   end
   fclose(fid);
end

