function fiff_write_epochs(name,data,datatype)
%
% function fiff_write_epochs(name,data)
%
% name     filename
% data     the data structure returned from fiff_write_evoked
%
%

% This function has been adjusted by Jan-Mathijs Schoffelen, inspired by the 
% fiff_write_evoked function, in order to achieve some more symmetry with
% respect to the reading and writing of epoched data files.
%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
% Revision 1.14  2009/03/31 01:12:30  msh
% Improved ID handling
%
% Revision 1.13  2009/03/30 11:37:37  msh
% Added copying of measurement info blocks from the original like in mne_browse_raw
%
% Revision 1.12  2008/03/13 19:18:07  msh
% Read and write FIFF_MEAS_DATE from/to FIFFB_MEAS_INFO as appropriate
%
% Revision 1.11  2006/10/04 20:12:37  msh
% Added fiff_read_evoked_all
% Modified fiff_pick_channels_evoked to handle multiple data sets
% Added bad channel writing to fiff_write_evoked
%
% Revision 1.10  2006/09/26 23:20:23  msh
% Moved block ID and parent block id to the meas block.
%
% Revision 1.9  2006/06/14 05:32:43  msh
% Added missing FIFF_NAVE to each aspect written.
%
% Revision 1.8  2006/05/29 16:57:32  msh
% Make sure that scan numbers are correct.
%
% Revision 1.7  2006/04/23 15:29:40  msh
% Added MGH to the copyright
%
% Revision 1.6  2006/04/18 20:44:46  msh
% Added reading of forward solution.
% Use length instead of size when appropriate
%
% Revision 1.5  2006/04/14 15:49:49  msh
% Improved the channel selection code and added ch_names to measurement info.
%
% Revision 1.4  2006/04/14 11:03:57  msh
% Changed fiff_write_id write a given id.
% Added parent id writing.
%
% Revision 1.3  2006/04/13 23:09:46  msh
% Further streamlining of the coordinate transformations.
%
% Revision 1.2  2006/04/12 13:13:51  msh
% Added fiff_find_evoked.m
% Use aspect_kind field name instead of aspect_type
%
% Revision 1.1  2006/04/12 10:29:02  msh
% Made evoked data writing compatible with the structures returned in reading.
%
%
me='MNE:mne_write_epochs';
if nargin < 2
    error(me,'File name and data required as an arguments');
end

%
FIFF = fiff_define_constants();
if nargin < 3 || isempty(datatype)
    datatype = FIFF.FIFFT_FLOAT;
end

if datatype ~= FIFF.FIFFT_FLOAT
    warning(me, 'reading and writing of data in numeric precision ~= float is only supported in FieldTrip and MNE-Python');
end

%
%  Create the file and save the essentials
%
fid = fiff_start_file(name);
fiff_start_block(fid,FIFF.FIFFB_MEAS);
fiff_write_id(fid,FIFF.FIFF_BLOCK_ID);
if ~isempty(data.info.meas_id)
    fiff_write_id(fid,FIFF.FIFF_PARENT_BLOCK_ID,data.info.meas_id);
end
%
%    Measurement info
%
fiff_start_block(fid,FIFF.FIFFB_MEAS_INFO);
%
%    Blocks from the original
%
blocks = [ FIFF.FIFFB_SUBJECT FIFF.FIFFB_HPI_MEAS FIFF.FIFFB_HPI_RESULT FIFF.FIFFB_ISOTRAK FIFF.FIFFB_PROCESSING_HISTORY ];
have_hpi_result = false;
have_isotrak    = false;
if ~isempty(blocks) && isfield(data.info,'filename') && ~isempty(data.info.filename)
    [ fid2, tree ] = fiff_open(data.info.filename);
    for k = 1:length(blocks)
        nodes = fiff_dir_tree_find(tree,blocks(k));
        fiff_copy_tree(fid2,tree.id,nodes,fid);
        if blocks(k) == FIFF.FIFFB_HPI_RESULT && isempty(nodes)
            have_hpi_result = true;
        end
        if blocks(k) == FIFF.FIFFB_ISOTRAK && ~isempty(nodes)
            have_isotrak = true;
        end
    end
    fclose(fid2);
end
%
%    General
%
fiff_write_float(fid,FIFF.FIFF_SFREQ,data.info.sfreq);
fiff_write_float(fid,FIFF.FIFF_HIGHPASS,data.info.highpass);
fiff_write_float(fid,FIFF.FIFF_LOWPASS,data.info.lowpass);
fiff_write_int(fid,FIFF.FIFF_NCHAN,data.info.nchan);
if ~isempty(data.info.meas_date)
    fiff_write_int(fid,FIFF.FIFF_MEAS_DATE,data.info.meas_date);
end
%
%    Coordinate transformations if the HPI result block was not there
%
if ~have_hpi_result
    if ~isempty(data.info.dev_head_t)
        fiff_write_coord_trans(fid,data.info.dev_head_t);
    end
    if ~isempty(data.info.ctf_head_t)
        fiff_write_coord_trans(fid,data.info.ctf_head_t);
    end
end
%
%  Channel information
%
ch_rename = fiff_make_ch_rename(data.info.chs);
fiff_write_ch_infos(fid,data.info.chs,false,ch_rename);
%
%    Polhemus data
%
if ~isempty(data.info.dig) && ~have_isotrak
    fiff_start_block(fid,FIFF.FIFFB_ISOTRAK);
    for k = 1:length(data.info.dig)
        fiff_write_dig_point(fid,data.info.dig(k))
    end
    fiff_end_block(fid,FIFF.FIFFB_ISOTRAK);
end
%
%    Projectors
%
fiff_write_proj(fid,data.info.projs,ch_rename);
%
%    CTF compensation info
%
fiff_write_ctf_comp(fid,data.info.comps,ch_rename);
%
%    Bad channels
%
if ~isempty(data.info.bads)
    fiff_start_block(fid,FIFF.FIFFB_MNE_BAD_CHANNELS);
    fiff_write_name_list(fid,FIFF.FIFF_MNE_CH_NAME_LIST,data.info.bads);
    fiff_end_block(fid,FIFF.FIFFB_MNE_BAD_CHANNELS);
end
%
%
fiff_end_block(fid,FIFF.FIFFB_MEAS_INFO);

%
% Events
%
eventlist = data.epoch.events';
fiff_start_block(fid,FIFF.FIFFB_MNE_EVENTS);
fiff_write_int(fid,FIFF.FIFF_MNE_EVENT_LIST,eventlist(:));
fiff_write_string(fid,FIFF.FIFF_DESCRIPTION,data.epoch.event_id);
fiff_end_block(fid,FIFF.FIFFB_MNE_EVENTS);

%
% One or more evoked data sets
%
fiff_start_block(fid,FIFF.FIFFB_PROCESSED_DATA);
%
fiff_start_block(fid,FIFF.FIFFB_MNE_EPOCHS);

%
% Comment is optional
%
if size(data.epoch.comment,2) > 0
    fiff_write_string(fid,FIFF.FIFF_COMMENT,data.epoch.comment);
end
%
% First and last sample
%
fiff_write_int(fid,FIFF.FIFF_FIRST_SAMPLE,data.epoch.tmin);
fiff_write_int(fid,FIFF.FIFF_LAST_SAMPLE,data.epoch.tmax);
%
% The epochs
%
for k = 1:numel(data.info.chs)
    decal = 1./data.info.chs(k).cal;
    if decal~=1
        data.epoch.epochs(:,k,:) = data.epoch.epochs(:,k,:).*decal;
    end
end
switch datatype
    case FIFF.FIFFT_FLOAT
        fiff_write_float_matrix(fid,FIFF.FIFF_EPOCH,data.epoch.epoch);
    case FIFF.FIFFT_DOUBLE
        fiff_write_double_matrix(fid,FIFF.FIFF_EPOCH,data.epoch.epoch);
    case FIFF.FIFFT_COMPLEX_FLOAT
        fiff_write_complex_matrix(fid,FIFF.FIFF_EPOCH,data.epoch.epoch);
    case FIFF.FIFFT_COMPLEX_DOUBLE
        fiff_write_double_complex_matrix(fid,FIFF.FIFF_EPOCH,data.epoch.epoch);
    otherwise
        error(me,'unsupported datatype requested for writing of the epoch data matrix');
end

%
% Add some other metadata that belongs to the MNE epochs object
%
if ~isempty(data.epoch.baseline)
  fiff_write_float(fid,FIFF.FIFF_MNE_BASELINE_MIN,data.epoch.baseline(1));
  fiff_write_float(fid,FIFF.FIFF_MNE_BASELINE_MAX,data.epoch.baseline(2));
end
fiff_write_int(fid,FIFF.FIFF_MNE_EPOCHS_SELECTION,data.epoch.selection);
fiff_write_string(fid,FIFF.FIFF_COMMENT,data.epoch.comment);
fiff_write_string(fid,FIFF.FIFF_MNE_EPOCHS_DROP_LOG,data.epoch.drop_log);

fiff_end_block(fid,FIFF.FIFFB_MNE_EPOCHS);

fiff_end_block(fid,FIFF.FIFFB_PROCESSED_DATA);

fiff_end_block(fid,FIFF.FIFFB_MEAS);

fiff_end_file(fid);
return;
