%%% Version: June 16th, 2017
%%%
%%% This function checks 
%%% either
%%% (a) whether model files and the resulting model strucutre are in line 
%%%     with agreed standards on model structure, naming, etc. There must
%%%     be the following files in the same directory as this
%%%     model checking file
%%%      <modelName>_indexing.m
%%%      <modelName>_parameters.m
%%%      <modelName>_ode.m
%%%      <modelName>_initialValues.m
%%%
%%% or
%%% (b) whether a given model structure is in line with agreed standards 
%%%     on model structure, naming, etc. There must be the following 
%%%     fields in the model structure:
%%%       model.I   - indexing structure with the following fields
%%%             I.nrOfStates
%%%             I.allStates
%%%             I.stateNames
%%%             I.nrOfPar
%%%             I.allPar
%%%             I.parNames
%%%       model.par - column vector of parameters values
%%%       model.ode - function handle to right hand side of ode
%%%       model.X0  - column vector of initial values
%%%
%%% Input:  (a) none, or (b) model struture
%%%
%%% Output: information about the model checking process
%%%
%%% author: Corinna Maier, Wilhelm Huisinga
%%%

function out = model_check(varargin)

if nargin == 0  %%% case (a) of the info in the header 
    
    %%%
    fprintf('\n Checking model generating functions ...');

    %%% no model structure passed on to be checked. Thus, check for
    %%% existence of neccessary files, build up the model structure and
    %%% check for consistence
    
    model = struct('name',[],'I',[],'ode',[],'X0',[],'par',[]);
    
    %%% check whether the model generating functions are in the current
    %%% folder ...
    
    %%% check whether there is an indexing file
    %%%
    indexingfile = dir( fullfile( '*indexing.m' ) );
    
    assert( exist(indexingfile.name, 'file') == 2,...
        'There is no indexing function for your model!')
    filenameparts      = strsplit(indexingfile.name,'.');
    modelname_indexing = filenameparts{1};
    
    %%% get the model name from indexing file name
    %%%
    filenameparts = strsplit(indexingfile.name,'_indexing');
    model.name = filenameparts{1};
       
    %%% check whether there is a parameter file
    %%%
    parametersfile = dir( fullfile( [model.name,'_parameters.m'] ) );
    
    assert( exist(parametersfile.name, 'file')==2,...
        'There is no parameters function for your model!')
    filenameparts           = strsplit(parametersfile.name,'.');
    modelname_parameters = filenameparts{1};
    
    %%% check whether there is an ode file specifying the model equations
    %%%
    odefile = dir( fullfile( [model.name,'_ode.m'] ) );
    
    assert( exist(odefile.name, 'file') == 2,...
        'There is no ode function for your model!')
    
    %%% check whether there is a file with initial values
    %%%
    initialValuesfile = dir( fullfile( [model.name,'_initialValues.m'] ) );
    
    assert( exist(initialValuesfile.name, 'file') == 2,...
        'There is no initialValues function for your model!')
    filenameparts           = strsplit(initialValuesfile.name,'.');
    modelname_initialValues = filenameparts{1};
    
    %%% build up model structure
    %%%
    model.I     = feval(modelname_indexing);
    model.X0    = feval(modelname_initialValues,model.I);
    eval(sprintf('model.ode   = @(t,X,par) %s_ode(t,X,par,model);',model.name));
    model.par   = feval(modelname_parameters,model);
    
elseif nargin == 1  %%% case (b) of the info in the header 
    
    %%%
    fprintf('\n Checking model structure ...');

    model = varargin{1};
    
    %%% check whether the input argument is called 'model' and has the
    %%% desiret fieldnames
    
    %%% check for model name
    assert(isfield(model,'name'),'Model name missing in struct model!');

    %%% check for model indexing
    assert(isfield(model,'I'),'Model indexing I missing in struct model!');

    %%% check for model ode
    assert(isfield(model,'ode'),'Model equations ode missing in struct model!');

    %%% check for initial values
    assert(isfield(model,'X0'),'Model initial values X0 missing in struct model!');

    %%% check for parameters
    assert(isfield(model,'par'),'Model parameters param missing in struct model!');
    
else
    
    %%% number of input arguments not compatable with this function
    
    assert(false,' Unknown number of input arguments!');
    
end;

fprintf(' OK! \n');

%%% -----------------------------------------------------------------------
%%% check if all necessary fields of the model struct exist
%%% -----------------------------------------------------------------------

%%% check whether the model structure has the required field names
%%%
fprintf(' Checking the field names of your model structure ...')

%%% check indexing structure
%%%
assert(~isempty(model.I),' model.I is empty!'); 

%%% states
assert(isfield(model.I,'nrOfStates'),' model.I must contain field I.nrOfStates!');
assert(isnumeric(model.I.nrOfStates),' I.nrOfStates must be numeric value!');
assert(model.I.nrOfStates>=0,' I.nrOfStates must be non-negative!');

assert(isfield(model.I,'allStates'),' Indexing model.I must contain I.allStates!');
assert(isfield(model.I,'stateName'),' Indexing model.I must contain I.stateName!');

%%% parameters
assert(isfield(model.I,'nrOfPar'),' model.I must contain field I.nrOfPar!');
assert(isnumeric(model.I.nrOfPar),' I.nrOfPar must be numeric value!');
assert(model.I.nrOfPar>=0,' I.nrOfPar must be non-negative!');

assert(isfield(model.I,'allPar'),' Indexing model.I must contain I.allPar!');
assert(isfield(model.I,'parName'),' Indexing model.I must contain I.parName!');


%%% check ode function
%%%
assert(isa(model.ode,'function_handle'),' model.ode must be a function handle!')

%model.ode(0,model.X0,model.par);



%%% check initial condition
%%%
assert(iscolumn(model.X0),' model.X0 must be a column vector!')


%%% check parameters
%%%
assert(iscolumn(model.par),' model.par must be a column vector!')

fprintf(' OK! \n');

fprintf('\n Well done! Your model is ready for use :-) \n\n');

out = model;



