function varargout = process_ERPimage( varargin )
% PROCESS_ERPIMAGE: Generate ERP image plot sorted by event metadata.
%
% USAGE:              [hFig, iDS, iFig] = process_ERPimage('Run', sProcess, sInputs)

% @=============================================================================
% This function is part of the CPL Toolbox written for Brainstorm software:
% 
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
% 
% THIS SOFTWARE IS PROVIDED "AS IS," AND THE AUTHORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% =============================================================================@
%
% Authors: Paul Kieffaber 2021
%  - modified from process_average.m & view_image of the Brainstorm software

eval(macro_method);
end


%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'ERP Image';
    sProcess.Category    = 'Custom';
    sProcess.SubGroup    = {'CPL', 'Visualization'};
    sProcess.Index       = 302;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/Averaging#Averaging';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data', 'results', 'timefreq', 'matrix'};
    sProcess.OutputTypes = {'data', 'results', 'timefreq', 'matrix'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 2;
    sProcess.isSeparator = 1;
    SelectOptions = {...
        '', ...                               % Filename
        '', ...                               % FileFormat
        'open', ...                           % Dialog type: {open,save}
        'Select Sorting Values...', ...       % Window title
        'ImportData', ...                     % LastUsedDir: {ImportData,ImportChannel,ImportAnat,ExportChannel,ExportData,ExportAnat,ExportProtocol,ExportImage,ExportScript}
        'single', ...                         % Selection mode: {single,multiple}
        'files', ...                          % Selection mode: {files,dirs,files_and_dirs}
        {{'.csv'},{'Comma separated values'},{'CSV'}}, ... % Limit to csv file format
        'EventsIn'};                          % DefaultFormats: {ChannelIn,DataIn,DipolesIn,EventsIn,MriIn,NoiseCovIn,ResultsIn,SspIn,SurfaceIn,TimefreqIn
    % Option: Event file
    sProcess.options.evtfile.Comment = 'Select Metadata file (.csv):';
    sProcess.options.evtfile.Type    = 'filename';
    sProcess.options.evtfile.Value   = SelectOptions;
    sProcess.options.tag.Comment = 'Enter Metadata Tag:';
    sProcess.options.tag.Type    = 'text';
    sProcess.options.tag.Value   = '';
    sProcess.options.direction.Comment = {'Ascending', 'Descending', 'Sort Direction'};
    sProcess.options.direction.Type    = 'radio_line';
    sProcess.options.direction.Value   = 1;
    sProcess.options.label1.Comment = '<U><B>Plot Options</B></U>:';
    sProcess.options.label1.Type    = 'label';
    sProcess.options.curve.Comment    = 'Add Curve Line';
    sProcess.options.curve.Type       = 'checkbox';
    sProcess.options.curve.Value      = 0;
end


%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess)

end


%% ===== RUN =====
function [hFig, iDS, iFig] = Run(sProcess, sInputs) 
    % Get filenames to import
    MetaFile  = sProcess.options.evtfile.Value{1};
    MetaFileFormat = sProcess.options.evtfile.Value{2};
    addCurve=sProcess.options.curve.Value;
    if isempty(MetaFile)
        bst_report('Error', sProcess, [], 'Event file not selected.');
        return
    end
    % Import the Meta file
    T=readtable(MetaFile,'Delimiter',',','ReadVariableNames',1);
    
    % Get the sorting column name
    sortCol = sProcess.options.tag.Value;
      % Check that length(sort values) == length(sInputs.FileName)
    Nsortvals = eval(['length(T.' sortCol ');']);
    if Nsortvals ~= length({sInputs.FileName})
        bst_report('Error', sProcess, [], 'Number of sorting values does not match the number of files.');
        return;
    end

    % Get sorting direction
    switch sProcess.options.direction.Value
        case 1
            direction = 'ascend';
        case 2
            direction = 'descend';
        otherwise
            bst_report('Error', sProcess, [], 'No sorting direction specified.');
        return;
    end
    
    %Will want to add functionality for PSD and Hilbert eventually
    % Check type of input files
    %if ~isempty(strfind(sInputs(1).FileName, 'timefreq_pac')) || ~isempty(strfind(sInputs(1).FileName, 'timefreq_dpac'))
    %    bst_report('Error', sProcess, [], ['Cannot average PAC maps after their computation.' 10 'Please use the process option "Save average PAC across trials" instead.']);
    %    return;
    %end
    
    % Sort the input files
    [DataFiles, sortVals] = SortFiles(sInputs, T, sortCol, direction);
    
    %Make Figure
    [hFig, iDS, iFig] = view_erpimage( DataFiles, 'erpimage', 'EEG');
    % Add curve (if requested)
    if addCurve
        [sMat, matName] = in_bst(sInputs(1).FileName);
        %Check if values <> times 
        if any(sortVals>max(sMat.Time)) || any(sortVals<min(sMat.Time))
            sortVals=sortVals./1000;
        end
        xVec=[];
        for i=1:length(sortVals)
            xVec=cat(2,xVec,find(abs(sMat.Time-sortVals(i))==min(abs(sMat.Time-sortVals(i)))));
        end
        kids=get(hFig,'children');
        hold(kids(3),'on');
        set(kids(3),'Ydir','normal')
        plot3(kids(3),xVec,1.5:1:length(sInputs)+.5,ones(length(sInputs)),'LineWidth',3,'color','k');
    end
end


%% ===== SORT FILES =====
function [DataFiles, sortVals] = SortFiles(sInputs, T, sortCol, direction)
    DataFiles={sInputs.FileName};
    sortMtx=cat(2,[1:length(DataFiles)]',eval(['T.' sortCol]));
    sortMtx=sortrows(sortMtx,2,direction);
    sortVals=sortMtx(:,2);
    DataFiles=DataFiles(sortMtx(:,1));
end