function varargout=cosmo_notify_test_skipped(reason)
% notify that a test in the test suite is skipped
%
% Usages:
%   - cosmo_notify_test_skipped(reason)
%
%       Input:
%           reason          string indicating why a test is skipped, and
%                           store reason internally in this function.
%
%   - skipped_tests=cosmo_notify_test_skipped()
%
%       Output:
%           skipped_tests   cell with strings containing the reason values
%                           stored internally
%
%   - cosmo_notify_test_skipped()
%
%       Side effect: this empties the internal list of skipped tests
%
% Notes:
%   - depending on the call stack, this function:
%       * when called through MOxUnit's moxunit_run_tests, it raises an
%         exception through  moxunit_throw_test_skipped_exception. When
%         moxunit_run_tests is finished testing, it can summarize which
%         tests were skipped.
%       * when called through cosmo_run_tests, no warning is shown and no
%         error is thrown. When cosmo_run_tests is finished testing, it can
%         summarize which tests were skipped.
%       * otherwise, a warning message is shown with the reason.
%
% See also: moxunit_throw_test_skipped_exception, cosmo_run_tests
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #

    persistent skipped_tests

    if isempty(skipped_tests)
        skipped_tests=cell(0);
    end

    if nargin==0
        varargout={skipped_tests};
        return;
    elseif iscellstr(reason)
        skipped_tests=reason;
        return
    end

    varargout=cell(0);

    switch reason
        case 'on'
            skipped_tests=cell(0);

        otherwise
            % notify that a unit test was skipped
            %
            db=dbstack('-completenames');

            db_idx=last_non_testing_suite_stack_index(db);

            db_up=db(db_idx);
            desc=sprintf('%s: %s (%s:%d)', db_up.name, reason, ...
                                    db_up.file, db_up.line);

            skipped_tests{end+1}=desc;

            if test_was_run_by_MOxUnit(db)
                moxunit_throw_test_skipped_exception(desc);
            elseif test_was_run_by_cosmo_run_tests(db)
                % do nothing
            else
                warning('%s',desc)
            end


    end

function tf=test_was_run_by_MOxUnit(db)
    tf=dbstack_contains_string(db,'@MOxUnit');

function tf=test_was_run_by_cosmo_run_tests(db)
    tf=dbstack_contains_string(db,'cosmo_run_tests.m');

function tf=dbstack_contains_string(db, string)
    tf=~isempty(first_stack_index_with_string(db, string));

function idx=first_stack_index_with_string(db, string)
    files={db.file};
    has_string=~cellfun(@isempty,regexp(files,string));
    idx=find(has_string,1,'first');


function idx=last_non_testing_suite_stack_index(db)
    if test_was_run_by_MOxUnit(db)
        suite_dir=fileparts(which('moxunit_runtests'));
        idx=first_stack_index_with_string(db, suite_dir)-1;

    elseif test_was_run_by_cosmo_run_tests(db)
        suite_dir=fileparts(which('runtests'));
        idx=first_stack_index_with_string(db, suite_dir)-1;

    else
        idx=[];
    end
