% EEG_TIME2PREV - returns a vector giving, for each event of specified ("target") type(s), 
%                   the delay (in ms) since the preceding event (if any) of specified 
%                   ("previous") type(s). Requires the EEG.urevent structure, plus 
%                   EEG.EVENT.urevent pointers to it. 
%
%           NOW SUPERSEDED BY EEG_CONTEXT
% Usage:
%           >> [delays,targets,urtargs,urprevs] = eeg_time2prev(EEG,{target},{previous});
% Inputs:
%  EEG      - structure containing an EEGLAB dataset
% {target}  - cell array of strings naming event type(s) of the specified target events 
%{previous} - cell array of strings naming event type(s) of the specified previous events 
%
% Outputs:
%  delays    - vector giving, for each event of a type listed in "target", the delay (in ms) 
%              since the last preceding event of a type listed in "previous" (0 if none such).
%  targets   - vector of indices of the "target" events in the event structure
%  urtargs   - vector of indices of the "target" events in the urevent structure
%  urprevs   - vector of indices of the "previous" events in the urevent structure (0 if none).
%
% Example:
% >> target = {'novel'};           % target event type 'novel'
% >> previous = {'novel', 'rare'}; % either 'novel' or 'rare'
% >> [delays,targets] = eeg_time2prev(EEG,target,previous);
%% Vector 'delays' now contains delays (in ms) from each 'novel' event to the previous
%% 'rare' OR 'novel' event, else 0 if none such. Vector 'targets' now contains the
%% 'novel' event indices.
%%
% Scott Makeig & Arnaud Delorme, SCCN/INC/UCSD, August 28, 2003

% Copyright (C) Scott Makeig & Arnaud Delorme, SCCN/INC/UCSD, August 28, 2003
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [delays,targets,urtargets,urprevs] = eeg_time2prev(EEG,target,previous);

verbose = 1; % FLAG (1=on|0=off)
nevents = length(EEG.event);

%
%%%%%%%%%%%%%%%%%%%% Test input arguments %%%%%%%%%%%%%%%%%%%%%%%%%
%
if ~iscell(target)
  error('2nd argument "target" must be a {cell array} of event type strings.');
  return
end
for k=1:length(target)
   if ~ischar([ target{k}{:} ])
       error('2nd argument "target" must be a {cell array} of event type strings.');
   end
end
if ~iscell(previous)
  error('3rd argument "previous" must be a {cell array} of event types.');
  return
end
for k=1:length(target) % make all target types strings
  if ~ischar(target{k})
    target{k} = num2str(target{k});
  end
end
for k=1:length(previous) % make all previous types strings
  if ~ischar(previous{k})
    previous{k} = num2str(previous{k});
  end
end
if ~isfield(EEG,'urevent')
  error('requires the urevent structure be present.');
  return
end
if length(EEG.urevent) < nevents
  error('WARNING: In dataset, number of urevents < number of events!?');
  return
end

% 
%%%%%%%%%%%%%%%%%%%% Initialize output arrays %%%%%%%%%%%%%%%%%%%%%%
%
delays    = zeros(1,nevents); % holds output times in ms
targets   = zeros(1,nevents); % holds indexes of targets
urtargets = zeros(1,nevents); % holds indexes of targets
urprevs   = zeros(1,nevents); % holds indexes of prevs

targetcount = 0; % index of current target
% Below:
%   idx   = current event index
%   uridx = current urevent index
%   tidx  = target type index
%   uidx  = previous urevent index
%   pidx  = previous type index
%
%%%%%%%%%%%for each event in the dataset %%%%%%%%%%%%%%%%%%%%
%
for idx = 1:nevents                                % for each event in the dataset
 %
 %%%%%%%%%%%%%%%%%%%%%%%% find target events %%%%%%%%%%%%%%%%%
 %
 uridx = EEG.event(idx).urevent;                   % find its urevent index
 istarget = 0;                                     % initialize target flag
 tidx = 1;                                         % initialize target type index
 while ~istarget & tidx<=length(target)            % for each potential target type
    if strcmpi(num2str(EEG.urevent(uridx).type),target(tidx))
      istarget=1;                                  % flag event as target
      targetcount = targetcount+1;                 % increment target count
      targets(targetcount) = idx;                  % save event index
      urtargets(targetcount) = uridx;              % save urevent index
      break                                        % stop target type checking
    else
      tidx = tidx+1;                               % else try next target type
    end
 end 

 if istarget  % if current event is a target type
  %
  %%%%%%%%%%%%%%%%%%% Find a 'previous' event %%%%%%%%%%%%%%%%%%
  %
  isprevious = 0;                                  % initialize previous flag
  uidx = uridx-1;                                  % begin with the previous urevent
  while uridx > 0
   pidx = 1;                                       % initialize previous type index
   while ~isprevious & pidx<=length(previous)      % for each previous event type
     if strcmpi(num2str(EEG.urevent(uidx).type),previous(pidx)) 
       isprevious=1;                               % flag 'previous' event
       urprevs(targetcount) = uidx;                % mark event as previous
       break                                       % stop previous type checking
     else
       pidx = pidx+1;                              % try next 'previous' event type
     end
   end  % pidx
   if isprevious
     break                                         % stop previous event checking
   else
     uidx = uidx-1;                                % keep checking for a 'previous' type event
   end % isprevious
  end % uidx
  %
  %%% Compute delay from current target to previous event %%%%%
  %
  if isprevious                                    % if type 'previous' event found
    delays(targetcount) = 1000/EEG.srate * ...
     (-1)*(EEG.urevent(uridx).latency - EEG.urevent(urprevs(targetcount)).latency);
  else
    delays(targetcount) = 0;                        % mark no previous event with 0
  end
  if verbose
    fprintf('%4d. (targ %s) %4d - (prev %s) %4d = %4.1f ms\n',...
                targetcount, targets(tidx),idx, ...
                             previous(pidx),urprevs(targetcount),...
                                          delays(targetcount));
  end % verbose
 end % istarget
end % event loop

%
%%%%%%%%%%%%%% Truncate the output arrays %%%%%%%%%%%%%%%%%%%%%%
%
if targetcount > 0
   targets   = targets(1:targetcount);
   urtargets = urtargets(1:targetcount);
   urprevs   = urprevs(1:targetcount);
   delays    = delays(1:targetcount);
else
   if verbose
     fprintf('eeg_time2prev(): No target type events found.\n')
   end
   targets   = [];
   urtargets = [];
   urprevs   = [];
   delays    = [];
end 
