function jsn = jsnirfcreate(varargin)
%
%    jsn=jsnirfcreate
%       or
%    jsn=jsnirfcreate(option)
%    jsn=jsnirfcreate('Format',format,'Param1',value1, 'Param2',value2,...)
%
%    Create an empty JSNIRF data structure defined in the JSNIRF
%    specification: https://github.com/NeuroJSON/jsnirf or a SNIRF data structure
%    based on the SNIRF specification at https://github.com/fNIRS/snirf
%
%    author: Qianqian Fang (q.fang <at> neu.edu)
%
%    input:
%        option (optional): option can be ignored. If it is a string with a
%             value 'snirf', this creates a default SNIRF data structure;
%             otherwise, a JSNIRF data structure is created.
%        format: same as option.
%        param/value:   a list of name/value pairs specify
%             additional subfields to be stored under the /nirs object.
%
%    output:
%        jsn: a default SNIRF or JSNIRF data structure.
%
%    example:
%        jsn=jsnirfcreate('data',mydata,'aux',myauxdata,'comment','test');
%
%    this file is part of JSNIRF specification: https://github.com/NeuroJSON/jsnirf
%
%    License: GPLv3 or Apache 2.0, see https://github.com/NeuroJSON/jsnirfy for details
%

% define empty SNIRF data structure with all required fields

defaultmeta = struct('SubjectID', 'default', 'MeasurementDate', datestr(now, 29), ...
                     'MeasurementTime', datestr(now, 'hh:mm:ss'), 'LengthUnit', 'mm', ...
                     'TimeUnit', 's', 'FrequencyUnit', 'Hz');
defaultsrcmap = struct('sourceIndex', [], 'detectorIndex', [], ...
                       'wavelengthIndex', [], 'dataType', 1, 'dataTypeIndex', 1);
defaultdata = struct('dataTimeSeries', [], 'time', [], 'measurementList', defaultsrcmap);
defaultaux = struct('name', '', 'dataTimeSeries', [], 'time', [], 'timeOffset', 0);
defaultstim = struct('name', '', 'data', []);
defaultprobe = struct('wavelengths', [], 'sourcePos2D', [], 'detectorPos2D', []);

nirsdata = struct('metaDataTags', defaultmeta, ...
                  'data', defaultdata, ...
                  'aux', defaultaux, ...
                  'stim', defaultstim, ...
                  'probe', defaultprobe);

% read user specified data fields - will validate format in future updates

if (nargin > 1 && bitand(nargin, 1) == 0)
    for i = 1:nargin * 0.5
        key = varargin{2 * i - 1};
        if (strcmpi(key, 'format'))
            key = 'format';
        end
        nirsdata.(key) = varargin{2 * i};
    end
end

jsn = struct();

% return either a SNIRF data structure, or JSNIRF data (enclosed in SNIRFData tag)

if ((nargin == 1 && strcmpi(varargin{1}, 'snirf')) || ...
    (isfield(nirsdata, 'format') && strcmpi(nirsdata.format, 'snirf')))
    if (isfield(nirsdata, 'format'))
        nirsdata = rmfield(nirsdata, 'format');
    end
    jsn = struct('formatVersion', '1.0', 'nirs', nirsdata);
else
    nirsdata.formatVersion = '1.0';
    len = length(fieldnames(nirsdata));
    nirsdata = orderfields(nirsdata, [len, 1:len - 1]);
    jsn = struct('SNIRFData', nirsdata);
end
