function test_suite = test_statcode()
% tests for cosmo_statcode
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;

function test_statcode_self()
    stats=get_test_stats();
    assertEqual(cosmo_statcode(stats),stats);

    ds=struct();
    ds.samples=[];
    assertEqual(cosmo_statcode(ds),[]);

    ds.sa.stats=stats;
    assertEqual(cosmo_statcode(ds),stats);

    aet=@(varargin)assertExceptionThrown(@()...
                            cosmo_statcode(varargin{:}),'');
    % store warning state
    warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(warning_state));
    cosmo_warning('off');

    % test illegal input
    aet({'()'});
    aet({'foo(;)'});
    aet({'Zscore()'},'foo');
    aet('Zscore');

    % unknown input
    s=cosmo_statcode({'foo'},'afni');
    assertEqual(s.BRICK_STATAUX,[]);

    s=cosmo_statcode({'foo'},'nifti');
    assertEqual(s.intent_code,0);
    assertEqual(s.intent_p1,0);
    assertEqual(s.intent_p1,0);
    assertEqual(s.intent_p1,0);

    % empty input
    assertEqual(cosmo_statcode({}),cell(0,1));
    assertEqual(cosmo_statcode({},'bv'),cell(0,1));
    assertEqual(cosmo_statcode({},'nifti'),struct());
    assertEqual(cosmo_statcode({},'afni'),...
                        cosmo_structjoin('BRICK_STATAUX',[]));




function test_statcode_bv()
    [stats,stats_proper]=get_test_stats();
    bv_statcode=cosmo_statcode(stats,'bv');
    bv_values={[],[1 5],[4 2 3],5,5,[]};
    nvalues=numel(bv_values);
    assertEqual(nvalues,numel(bv_statcode))

    for j=1:numel(bv_values)
        bv_value=bv_values{j};

        s=struct();
        nv=numel(bv_value);

        if nv==0
            s.Type=0;
        else
            s.Type=bv_value(1);
            for k=1:(nv-1)
                label=sprintf('DF%d',k);
                s.(label)=bv_value(k+1);
            end
        end

        assertEqual(s,bv_statcode{j});
    end

    bv_map=struct();
    bv_map.VMRDimX=[];
    bv_map.VMRDimX=[];

    map_cell=cell(nvalues,1);
    for k=1:numel(map_cell)
        m=struct();
        m.DF1=0;
        m.DF2=0;
        m.DF3=0;
        m.Type=0;

        if ~isempty(bv_statcode{k})
            m=cosmo_structjoin(m,bv_statcode{k});
        end
        map_cell{k}=m;
    end

    bv_map.Map=cat(1,map_cell{:});
    assertEqual(cosmo_statcode(bv_map),stats_proper);



function test_statcode_afni()
    [stats,stats_proper]=get_test_stats();
    afni_statcode=cosmo_statcode(stats,'afni');
    afni_struct=struct();
    afni_struct.BRICK_STATAUX=[1 3 1 5 2 4 2 2 3 3 5 0 4 5 0];
    assertEqual(afni_statcode,afni_struct);

    afni_struct.DATASET_RANK=[NaN numel(stats)];
    assertEqual(cosmo_statcode(afni_struct),stats_proper);

    % error for too many elements
    afni_struct.BRICK_STATAUX(end+1)=0;
    afni_struct.BRICK_STATAUX(end+1)=0;
    assertExceptionThrown(@()cosmo_statcode(afni_struct),'');
    afni_struct.BRICK_STATAUX=afni_struct.BRICK_STATAUX(1:(end-3));
    assertExceptionThrown(@()cosmo_statcode(afni_struct),'');
    afni_struct.BRICK_STATAUX=afni_struct.BRICK_STATAUX(1:(end-6));
    assertExceptionThrown(@()cosmo_statcode(afni_struct),'');

function test_statcode_nifti()
    stats=get_test_stats();

    % NIFTI does not support multiple stats
    % silence warning
    warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(warning_state));
    cosmo_warning('off');

    assertEqual(cosmo_statcode(stats,'nifti'),struct());
    stats=repmat(stats(3),6,1);
    stats_proper=stats;

    nifti_statcode=cosmo_statcode(stats,'nifti');
    nifti_dime=struct();
    nifti_dime.intent_code=4;
    nifti_dime.intent_p1=2;
    nifti_dime.intent_p2=3;
    nifti_dime.intent_p3=0;

    assertEqual(nifti_statcode,nifti_dime);
    nifti_hdr=struct();
    nifti_hdr.dime=nifti_dime;
    nifti_hdr.dime.dim=[NaN NaN NaN NaN 1 numel(stats) 1];
    assertEqual(cosmo_statcode(nifti_hdr),stats_proper);





function [stats,stats_proper]=get_test_stats()
    stats={'none';'Ttest(5)';'Ftest(2,3)';'Zscore';'Zscore()';''};
    stats_proper=stats;
    stats_proper{1}='';
    stats_proper{4}='Zscore()';
    stats_proper{6}='';
