function D = spm_eeg_fuse(S)
% Fuse MEG and EEG datasets to create a multimodal dataset
% FORMAT D = spm_eeg_fuse(S)
%
% S           - input structure (optional)
%  fields of S:
%   S.D       - character array containing filenames of M/EEG mat-files
%   S.prefix     - prefix for the output file (default - 'u')
%
% D        - MEEG object (also written to disk, with a 'u' prefix)
%__________________________________________________________________________
%
% Vladimir Litvak
% Copyright (C) 2008-2022 Wellcome Centre for Human Neuroimaging


%-Startup
%--------------------------------------------------------------------------
spm('FnBanner', mfilename);
spm('FigName','M/EEG fuse'); spm('Pointer','Watch');

if ~isfield(S, 'prefix'),       S.prefix = 'u';           end

%-Load MEEG data
%--------------------------------------------------------------------------
D = S.D;

if ischar(D)
    F = cell(1,size(D,1));
    try
        for i = 1:size(D, 1)
            F{i} = spm_eeg_load(deblank(D(i, :)));
        end
        D = F;
    catch
        error('Trouble reading files');
    end
end

Nfiles = numel(D);

if Nfiles < 2
    error('Need at least two files for fusion.');
end

%-Check input and determine number of new number of trial types
%--------------------------------------------------------------------------
channels = {};
modalities = {};
isTF   =  strncmpi(D{1}.transformtype,'TF',2); % TF and TFphase

for i = 1:Nfiles
    if ~isequal(D{i}.transformtype, D{1}.transformtype)
        error(['The datasets do not contain the same kind of data.\n'...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if D{1}.ntrials ~= D{i}.ntrials
        error(['Data don''t have the same number of trials.\n' ...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if ~isequal(D{1}.conditions, D{i}.conditions)
        error(['Data don''t have the same condition labels.\n' ...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if D{1}.nsamples ~= D{i}.nsamples
        error(['Data don''t have the same number of time points.\n' ...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if D{1}.fsample ~= D{i}.fsample
        error(['Data don''t have the same sampling rate.\n' ...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if isTF &&  ~isequal(D{1}.frequencies, D{i}.frequencies)
        error(['Data don''t have the same frequencies.\n' ...
            'There is a difference between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    end
    
    if ~isempty(intersect(channels, D{i}.chanlabels))
        error(['Files to be fused should not have overlapping channel sets.\n' ...
            'There is an overlap in channel sets between files\n\t%s\nand\n\t%s.'], ...
            D{1}.fname, D{i}.fname);
    else
        channels = [channels, D{i}.chanlabels];
    end
    
    modalities = [modalities {D{i}.modality}];
end

Nchannels = numel(channels);

%-Arrange modalities in a fixed order
%--------------------------------------------------------------------------
[sel1, sel2] = spm_match_str({'Multimodal', 'MEG', 'EEG', 'LFP', 'Other'}, modalities);
D = D(sel2);
modalities = modalities(sel2);

%-Generate new meeg object with new filenames
%--------------------------------------------------------------------------
Dout = D{1};
[p, f, x] = fileparts(fnamedat(Dout));

if ~isTF
    Dout = clone(Dout, fullfile(pwd, [S.prefix f x]), [Nchannels Dout.nsamples Dout.ntrials]);
else
    Dout = clone(Dout, fullfile(pwd, [S.prefix f x]), [Nchannels Dout.nfrequencies Dout.nsamples Dout.ntrials]);
end


%-Write files
%--------------------------------------------------------------------------

spm_progress_bar('Init', Dout.ntrials, 'Trials written');
if Dout.ntrials > 100, Ibar = floor(linspace(1, Dout.ntrials, 100));
else Ibar = [1:Dout.ntrials]; end

for t = 1:Dout.ntrials
    k = 1;
    for i = 1:Nfiles
        if ~isTF
            Dout(k:(k+D{i}.nchannels-1), :, t) =  D{i}(:, :, t);
        else
            Dout(k:(k+D{i}.nchannels-1), :, :, t) =  D{i}(:, :, :, t);
        end
    k = k + D{i}.nchannels;
    end
    if ismember(t, Ibar), spm_progress_bar('Set', t); end
end

spm_progress_bar('Clear');

% Update the header data separately to only do it once
k = 1;
rejected = Dout.badtrials;
for i = 1:Nfiles
    rejected = [rejected D{i}.badtrials];
    
    Dout = chanlabels(Dout, k:(k+D{i}.nchannels-1), chanlabels(D{i}));
    Dout = chantype(Dout, k:(k+D{i}.nchannels-1), chantype(D{i}));
    if ~isempty(badchannels(D{i}))
        Dout = badchannels(Dout, k+badchannels(D{i})-1, 1);
    end
    Dout = units(Dout, k:(k+D{i}.nchannels-1), units(D{i}));
    Dout = coor2D(Dout, k:(k+D{i}.nchannels-1), coor2D(D{i}, ':'));
    
    k = k + D{i}.nchannels;
end

Dout = badtrials(Dout, rejected, 1);


%-Set sensor locations
%--------------------------------------------------------------------------
[junk, newmodalities] = modality(Dout, 1);
if ismember('MEG', newmodalities) && isempty(Dout.sensors('MEG'))
    for i = 1:numel(modalities)
        if isequal(modalities{i}, 'MEG') && ~isempty(D{i}.sensors('MEG'))
            Dout = sensors(Dout, 'MEG', D{i}.sensors('MEG'));
            Dout = fiducials(Dout, D{i}.fiducials);
            break;
        end
    end
end

if ismember('EEG', newmodalities) && isempty(Dout.sensors('EEG'))
    warning('Assigning default EEG sensor locations. Reload individual locations if necessary.');
    S1 = [];
    S1.D = Dout;
    S1.task = 'defaulteegsens';
    S1.updatehistory = 0;
    Dout = spm_eeg_prep(S1);
end

%-Remove previous inversions.
%--------------------------------------------------------------------------
if isfield(Dout, 'inv')
    Dout = rmfield(Dout, 'inv');
end

%-Save new M/EEG data
%--------------------------------------------------------------------------
Dout = Dout.history(mfilename, S, 'reset');
save(Dout);

D = Dout;

%-Cleanup
%--------------------------------------------------------------------------
spm_progress_bar('Clear');
spm('FigName','M/EEG fuse: done'); spm('Pointer','Arrow');
