function [ success ] = rfc(pFilename, pFloatDetails, pData, pTrajectory)
%RFC Saves the given data to the filename in RFC format.
%
%   Parameters:
%       pFilename (string) The destination filename.
%       pFloatDetails (struct) The FLOAT section that is stored in an RFB
%       file.
%       pData (matrix) The data that should be written to the RFC file.
%           Each line contains one set of data. The matrix format needs to
%           be the following:
%           IFLAG MESSAGE_NUMBER MESSAGE_DATE TEMP PRES LAT LON u v w
%       pTrajectory (struct) The trajectory data according to the memory
%           data format specification, see projects wiki.


%% Initialize return variables
success = false;

%% Initialize variables required for processing
headerString = '';
dataString = '';

%% Parameter check

parameterError = false;


if (~isstring(pFilename) && ~ischar(pFilename))
    warning([mfilename ': Given filename is neither a string nor a char!']);
    parameterError = true;
end
if (~isstruct(pFloatDetails))
    warning([mfilename ': Given float details is not a struct!']);
    parameterError = true;
end
expectedDataColumns = 10;
if (size(pData, 2) ~= expectedDataColumns)
    warning([mfilename ': Given data has ' site(pData, 2) ' columns, but ' ...
        num2str(expectedDataColumns) ' expected!']);
    parameterError = true;
end

if (parameterError)
    return;
else
    clear parameterError;
end

%% Replace all NaN with default values
defaultValues = repmat(-999, 10);
defaultValues(4) = -9.99; % temperature default value
% start at index 4 because the first three do not have default values
for i = 4:size(pData, 2)
    nanIndex = find(isnan(pData(:, i)));
    if ~isempty(nanIndex)
        pData(nanIndex, i) = repmat(defaultValues(i), 1, size(pData, 1));
    end
    clear nanIndex;
end

%% Prepare header and add it to the file string

% FLOAT NAME
floatname = num2str(pFloatDetails.floatname);
% FLOAT CYCLE
cycle = num2str(pFloatDetails.cycle(1));
% LAUNCH PARAMETER
launchPositionLat = num2str(pFloatDetails.cycle(2), '%3.2f');
launchPositionLon = num2str(pFloatDetails.cycle(3), '%3.2f');
launchTime = [pFloatDetails.launchtime, 0];
launchTimeRafosDays = num2str( ...
    artoa.convert.dmy2rd(launchTime(3), launchTime(2), launchTime(1)) ...
);
launchTime = num2str(launchTime);
% RECOVER PARAMETER
recoverTime = [pFloatDetails.recovertime, 0];
recoverTimeRafosDays = num2str( ...
    artoa.convert.dmy2rd(recoverTime(3), recoverTime(2), recoverTime(1)) ...
);
recoverTime = num2str(recoverTime);
% FIRST SURFACE POSITION
surfacePositionLat = num2str(pFloatDetails.cycle(9), '%3.2f');
surfacePositionLon = num2str(pFloatDetails.cycle(10), '%3.2f');
% CYCLE PARAMETER
floatCycleStartTime = [pFloatDetails.cycle(4:8), 0]; % seconds always zero
floatCycleStartTimeRafosDays = num2str( ...
    artoa.convert.dmy2rd(floatCycleStartTime(3), floatCycleStartTime(2), floatCycleStartTime(1)) ...
    + artoa.convert.hms2rd(floatCycleStartTime(4), floatCycleStartTime(5), 0) ...
);
floatCycleStartTime = num2str(floatCycleStartTime);
floatCycleEndTime = [pFloatDetails.cycle(11:15), 0]; % seconds always zero
floatCycleEndTimeRafosDays = num2str( ...
    artoa.convert.dmy2rd(floatCycleEndTime(3), floatCycleEndTime(2), floatCycleEndTime(1)) ...
    + artoa.convert.hms2rd(floatCycleEndTime(4), floatCycleEndTime(5), 0) ...
);
floatCycleEndTime = num2str(floatCycleEndTime);

header = { ...
    ['** Float: ' floatname], ...
    ['** Variables: InterpFlag LineNum RafosDay  Temp  Pres  Lat  Lon  U     V     W'], ...
    ['** Units    : #          #       #         degC  dbar  deg  deg  cm/s  cm/s  mm/s'], ...
    ['** Dummies  : NA         NA      NA        -9.99 -999  999  999   999   999   999'], ...
    ['** Cycle    : ' cycle], ...
    ['** Launch position (Cycle Start position): ' ...
        launchPositionLat ' ' launchPositionLon], ...
    ['** Surface position (Cycle End position) : ' ...
        surfacePositionLat ' ' surfacePositionLon], ...
    ['** Cycle Start time             : ' floatCycleStartTime ' (RAFOS day ' floatCycleStartTimeRafosDays ')'], ...
    ['** Launch time                  : ' launchTime ' (RAFOS day ' launchTimeRafosDays ')'], ...
    ['** Cycle End time               : ' floatCycleEndTime ' (RAFOS day ' floatCycleEndTimeRafosDays ')'], ...
    ['** First surface Position time  : ' recoverTime ' (RAFOS day ' recoverTimeRafosDays ')'], ...
    ['** Float clock offset (init/final)  : ' num2str(pFloatDetails.offset(1,end)) ' / ' num2str(pFloatDetails.offset(2,end)),' seconds'], ...
    ['** -------'] ...
};


headerString = strjoin(header, newline);

%% COLLECT DATA STRING

for i = 1:size(pData, 1)
    dataString = [ ...
        dataString ...
        sprintf('%12d%12d%12.2f%12.3f%12.1f%12.3f%12.3f%12.2f%12.2f%12.2f\n', pData(i, :)) ...
    ];
end

%% IF NO TRAJECTORY AVAILABLE
if (nargin == 3)
    headerString = [headerString newline ' *   No trajectory information, flt not tracked.' newline];
    saveToFile(pFilename, headerString, dataString);
    success = true;
    return;
elseif (~isstruct(pTrajectory))
    warning('Trajectory variable is not a struct. It will NOT be used!');
end

%% TRAJECTORY IS AVAILABLE
if (pTrajectory.dopplerCorrection == 1)
    dopplerCorrectionUsed = 'yes';
else
    dopplerCorrectionUsed = 'no';
end

trajectoryHeader = { ...
    ['** Tracking method: ' char(pTrajectory.trackingMethod)], ...
    ['** Interpolation method: ' char(pTrajectory.interpolationMethod)], ...
    ['** Interpolation step size: ' num2str(pTrajectory.interval) ' hours'], ...
    ['** Interpolation gap size: ' num2str(pTrajectory.gapSize)], ...
    ['** Doppler correction: ' dopplerCorrectionUsed], ...
    ['** -------'], ...
    ['** Sound source combinations: (rafos day, sound sources, reference position, sound speed)'] ...
};

trajectoryHeader = strjoin(trajectoryHeader, newline);

soundSourcesHeader = '';
for i = 1:length(pTrajectory.soundSources)
    currentCombination = pTrajectory.soundSources(i);
    soundSourcesHeader = [ ...
        soundSourcesHeader ...
        '**    ' num2str(currentCombination.begin) ' to ' num2str(currentCombination.end) ': ' ...
        strjoin(currentCombination.sources, ' ') ' ' ...
        num2str(currentCombination.referencePosition) ' ' ...
        num2str(currentCombination.soundSpeed) ...
        newline ...
    ];
end

soundSourcesHeader = [ ...
    soundSourcesHeader ...
    '** -------' newline ...
    '** Additional Float clock offsets, seconds (beginning, end): ' ...
    num2str(pTrajectory.additionalFloatOffsetBegin) ...
    ' ' ...
    num2str(pTrajectory.additionalFloatOffsetEnd) newline ...
    '** -------' newline ...
    ' *   l  ----------' ...
];

headerString = [ ...
    headerString newline...
    trajectoryHeader newline ...
    soundSourcesHeader newline ...
];

%% Save to file
saveToFile(pFilename, headerString, dataString);

%% Update return variable
success = true;


%% Nested functions

    function saveToFile(pFilename, pHeader, pData)
        fid = fopen(pFilename, 'w');
        fprintf(fid, pHeader);
        fprintf(fid, pData);
        fclose(fid);
    end

end
