%TOOLKITS class definition
%
%   Usage:
%      self=toolkits();

classdef toolkits < dynamicprops
    properties (SetAccess=public) 
		 DefaultAnalysis           = struct();
		 %The other properties are dynamic
	 end
	 methods
		 function self = toolkits(varargin) % {{{
			 switch nargin
				 case 0
					 self=setdefaultparameters(self);
				 case 1
					 self=structtoobj(self,varargin{1});
				 otherwise
					 error('constructor not supported');
				 end
			 end % }}}
		 function self = addoptions(self,analysis,varargin) % {{{
		 % Usage example:
		 %    md.toolkits=addoptions(md.toolkits,'StressbalanceAnalysis',FSoptions());
		 %    md.toolkits=addoptions(md.toolkits,'StressbalanceAnalysis');

			 %Create dynamic property if property does not exist yet
			 if ~ismember(analysis,properties(self)),
				 self.addprop(analysis);
			 end

			 %Add toolkits options to analysis
			 if nargin==3, self.(analysis) = varargin{1}; end
		 end
		 %}}}
		 function self = setdefaultparameters(self) % {{{

			 %default toolkits: 
			 if IssmConfig('_HAVE_PETSC_'),
				 %MUMPS is the default toolkits
				 if IssmConfig('_HAVE_MUMPS_'),
					 self.DefaultAnalysis           = mumpsoptions();
				 else
					 self.DefaultAnalysis           = iluasmoptions(); 
				 end
			 else
				 if IssmConfig('_HAVE_MUMPS_'),
					 self.DefaultAnalysis           = issmmumpssolver(); 
				 elseif IssmConfig('_HAVE_GSL_'),
					 self.DefaultAnalysis           = issmgslsolver(); 
				 else 
					 disp('WARNING: Need at least Mumps or Gsl to define an issm solver type, no default solver assigned');
				 end
			 end

		 end % }}}
		 function disp(self) % {{{
			 analyses=properties(self);
			 disp(sprintf('List of toolkits options per analysis:\n'));
			 for i=1:numel(analyses),
				 analysis=analyses{i};
				 disp([analysis ':']);
				 disp(self.(analysis));
			 end
		 end % }}}
		 function md = checkconsistency(self,md,solution,analyses) % {{{
			 analyses=properties(self);
			 for i=1:numel(analyses),
				 if isempty(fieldnames(self.(analyses{i})))
					 md = checkmessage(md,['md.toolkits.' analyses{i} ' is empty']);
				 end
			 end
		 end % }}}
		 function ToolkitsFile(toolkits,filename) % {{{
		 %TOOLKITSFILE - build toolkits file
		 %
		 %   Build a Petsc compatible options file, from the toolkits model field  + return options string. 
		 %   This file will also be used when the toolkit used is 'issm' instead of 'petsc'
		 %
		 %   Usage:     ToolkitsFile(toolkits,filename);

			 %open file for writing
			 fid=fopen(filename,'w');
			 if fid==-1,
				 error(['ToolkitsFile error: could not open ' filename ' for writing']);
			 end

			 %write header
			 fprintf(fid,'%s%s%s\n','%Toolkits options file: ',filename,' written from Matlab toolkits array');

			 %start writing options
			 analyses=properties(toolkits);
			 for i=1:numel(analyses),
				 analysis=analyses{i};
				 options=toolkits.(analysis);

				 %first write analysis:
				 fprintf(fid,'\n+%s\n',analysis); %append a + to recognize it's an analysis enum

				 %now, write options
				 optionslist=fieldnames(options);
				 for j=1:numel(optionslist),
					 optionname=optionslist{j};
					 optionvalue=options.(optionname);

					 if isempty(optionvalue),
						 %this option has only one argument
						 fprintf(fid,'-%s\n',optionname);
					 else
						 %option with value. value can be string or scalar
						 if isnumeric(optionvalue),
							 fprintf(fid,'-%s %g\n',optionname,optionvalue);
						 elseif ischar(optionvalue),
							 fprintf(fid,'-%s %s\n',optionname,optionvalue);
						 else
							 error(['ToolkitsFile error: option ' optionname ' is not well formatted']);
						 end
					 end
				 end
			 end

			 fclose(fid);
		 end %}}}
		function savemodeljs(self,fid,modelname) % {{{
	
			analyses=properties(self);
			 for i=1:numel(analyses),
				 if isempty(fieldnames(self.(analyses{i})))
					 error(['md.toolkits.' analyses{i} ' is empty']);
				 else
					 writejsstruct(fid,[modelname '.toolkits.' analyses{i}],self.(analyses{i}));
				 end
			 end
	
		end % }}}
	 end
 end
