function concatStructTSG( hMainFig, tsg_old )
%
% Concatenate some elements of a TSG structure. Mainly :
% - TSG data members (DAYD, DATE, LATX, LONX, SSPS, SSJT, SSTP)
% - Discrete data (_EXT) members (DAYD, DATE, LATX, LONX, SSPS, SSTP) 
%
% Right now, the function do not concatenate :
% - Calibration coefficent
% - '_HIST'
% - preference
%
% If the concatenanted TSG structures have identical dates, the double
% are supressed.
%
% This function is called by read_data.m

% The function calls :
% concatNumTsg    - At the end of this file
% concatInt8Tsg   - At the end of this file
% supTsgDouble    - At the end of this file
% supTsgExtDouble - At the end of this file
%
% Input
% hMainFig .... Handle to the main application
% tsg_old ..... TSG struct array, the first loaded in tsgqc. The data will
%               be concatenated in this variable
%
% The tsg structure array to concatenate has been initialised in
% read_data and saved in the application data variable 'tsg_data'.
% 
% $Id$

% Retrieve the new tsg struct that we want to concatenate 
% -------------------------------------------------------
tsg_new = getappdata( hMainFig, 'tsg_data' );

% Get NO_CONTROL code value
% -------------------------
NO_CONTROL = tsg_old.qc.hash.NO_CONTROL.code;

% Sort the date in ascending order. 
% iOrder is used to sort the members of the strcture
% DAYD is not concatenated right now because the function concatNumTsg uses
% the variable tsg.DAYD to know the size of the arrays.
% ----------------------------------------------------------------------
DAYD = [tsg_old.DAYD; tsg_new.DAYD];
[DAYD, iOrder] = sort(DAYD);

% Concatenate the arrays
% ----------------------
tsg_old.DATE = [tsg_old.DATE; tsg_new.DATE];
tsg_old.DATE = tsg_old.DATE(iOrder,:);

tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'LATX');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'LONX');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'POSITION_QC');
%
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SPDC');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'PRES');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'FLOW');
%
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'CNDC');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'CNDC_STD');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'CNDC_CAL');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'CNDC_FREQ');
%
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSJT_QC');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT_STD');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT_CAL');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT_FREQ');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT_ADJUSTED');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSJT_ADJUSTED_ERROR');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSJT_ADJUSTED_QC');
% % concatStrTsg( iOrder, tsg_old, tsg_new, 'SSJT_ADJUSTED_HIST');
%
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSPS_QC');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS_STD');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS_CAL');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS_ADJUSTED');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS_ADJUSTED_ERROR');
tsg_old = concatInt8Tsg( iOrder,  NO_CONTROL, tsg_old, tsg_new, 'SSPS_ADJUSTED_QC');
% % concatStrTsg( iOrder, tsg_old, tsg_new, 'SSPS_ADJUSTED_HIST');
%
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSTP_QC');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP_CAL');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP_FREQ');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP_ADJUSTED');
tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP_ADJUSTED_ERROR');
tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSTP_ADJUSTED_QC');
% % concatStrTsg( iOrder, tsg_old, tsg_new, 'SSTP_ADJUSTED_HIST');

tsg_old.DAYD = DAYD;

% Suppress double. Compare the dates
% ----------------------------------
tsg_old = supTsgDouble(tsg_old);

% Discrete samples
% ----------------
if ~isempty(tsg_old.DAYD_EXT) || ~isempty(tsg_new.DAYD_EXT)
  
  % Sort the date in ascending order.
  % iOrder is used to sort the members of the strcture
  % DAYD is not concatenated right now because the function concatNumTsg uses
  % the variable tsg.DAYD to know the size of the arrays.
  % ----------------------------------------------------------------------
  DAYD_EXT = [tsg_old.DAYD_EXT; tsg_new.DAYD_EXT];
  [DAYD_EXT, iOrder] = sort(DAYD_EXT);
  
  % Concatenate the arrays
  % ----------------------
  tsg_old.DATE_EXT = [tsg_old.DATE_EXT; tsg_new.DATE_EXT];
  tsg_old.DATE_EXT = tsg_old.DATE_EXT(iOrder,:);
  
  tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'LATX_EXT');
  tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'LONX_EXT');
  tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSPS_EXT');
  tsg_old = concatStrTsg( iOrder, tsg_old, tsg_new, 'SSPS_EXT_BOTTLE');
  tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSPS_EXT_QC');
  tsg_old = concatStrTsg( iOrder, tsg_old, tsg_new, 'SSPS_EXT_TYPE');
  tsg_old = concatStrTsg( iOrder, tsg_old, tsg_new, 'SSPS_EXT_ANALDATE');
  tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, 'SSTP_EXT');
  tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, 'SSTP_EXT_QC');
  tsg_old = concatStrTsg( iOrder, tsg_old, tsg_new, 'SSTP_EXT_TYPE');
  
  % if ~isempty(tsg_old.DAYD_EXT)
  %   [tsg_old.DAYD_EXT, iOrder] = sort(tsg_old.DAYD_EXT);
  %   tsg_old.DATE_EXT           = tsg_old.DATE_EXT(iOrder,:);
  %   tsg_old.LATX_EXT           = tsg_old.LATX_EXT(iOrder);
  %   tsg_old.LONX_EXT           = tsg_old.LONX_EXT(iOrder);
  %   tsg_old.SSPS_EXT           = tsg_old.SSPS_EXT(iOrder);
  %   tsg_old.SSPS_EXT_QC        = tsg_old.SSPS_EXT_QC(iOrder);
  %   tsg_old.SSPS_EXT_BOTTLE    = tsg_old.SSPS_EXT_BOTTLE(iOrder,:);
  %   tsg_old.SSPS_EXT_TYPE      = tsg_old.SSPS_EXT_TYPE(iOrder,:);
  %   tsg_old.SSPS_EXT_ANALDATE  = tsg_old.SSPS_EXT_ANALDATE(iOrder,:);
  %   tsg_old.SSTP_EXT           = tsg_old.SSTP_EXT(iOrder);
  %   tsg_old.SSTP_EXT_QC        = tsg_old.SSTP_EXT_QC(iOrder);
  %   tsg_old.SSTP_EXT_TYPE      = tsg_old.SSTP_EXT_TYPE(iOrder,:);
  % end
  
  tsg_old.DAYD_EXT = DAYD_EXT;
  
  % Suppress Double. Compare the dates
  % ----------------------------------
  tsg_old = supTsgExtDouble(tsg_old);
  
end

setappdata( hMainFig, 'tsg_data', tsg_old );

end

%% ************************************************************************
function tsg_old = concatNumTsg( iOrder, tsg_old, tsg_new, Para)
%
% function concatNumTsg : Concatenate 2 numeric TSG arrays
%
% Input
% iOrder - Indicies to organise the array in time ascending order
% tsg_old - First TSG structure
% tsg_new - TSG structure that we want to concatenate
% Para - Member of the structures to concatenate
%
% Output
% tsg_old - TSG structure
%

% Detect if the variable Para is a TSG parameter or an EXT parameter
% Choose the right date
% ------------------------------------------------------------------
if isempty( strfind(Para, 'EXT') )
  new_DAYD = tsg_new.DAYD;
  old_DAYD = tsg_old.DAYD;
else
  new_DAYD = tsg_new.DAYD_EXT;
  old_DAYD = tsg_old.DAYD_EXT;
end

% If tsg_new.Para and tsg_old.Para are empty nothing is done
% ----------------------------------------------------------
if isempty(tsg_new.(Para)) && isempty(tsg_old.(Para))
  return;
  
  % If only tsg_new.PARA is empty, fill it with NaN. The dimension of the
  % final array must must be equal to the sum of the dimension of tsg.DAYD
  % and tsg_old.DAYD
  % ----------------------------------------------------------------------
elseif isempty(tsg_new.(Para))
  tsg_new.(Para) = NaN * ones( size( new_DAYD ) );
  
  % See preceding comment
  % ---------------------
elseif isempty(tsg_old.(Para))
  tsg_old.(Para)  = NaN * ones( size( old_DAYD ) );
end

% Concatenation
% -------------
tsg_old.(Para) = [tsg_old.(Para); tsg_new.(Para)];

% Re-order the struct array
% -------------------------
tsg_old.(Para) = tsg_old.(Para)(iOrder);

end

%% *************************************************************************
function tsg_old = concatStrTsg( iOrder, tsg_old, tsg_new, Para)
%
% function concatStrTsg : Concatenate 2 string arrays
%
% Input
% iOrder - Indicies to organise the array in time ascending order
% tsg_old - First TSG structure
% tsg_new - TSG structure that we want to concatenate
% Para - Member of the structures to concatenate
%
% Output
% tsg_old - TSG structure
%
  
  % Initialize default strings
  % --------------------------
  if ~isempty( strfind(Para, 'ANALDATE') )
    label = '19500101000000';
  elseif ~isempty( strfind(Para, 'BOTTLE') )
    label = '0';
  elseif ~isempty( strfind(Para, 'TYPE') )
    label = 'UNKN';
  end

% Detect if the variable Para is a TSG parameter or an EXT parameter
% Choose the right date
% ------------------------------------------------------------------
if isempty( strfind(Para, 'EXT') )
  new_DAYD = tsg_new.DAYD;
  old_DAYD = tsg_old.DAYD;
else
  new_DAYD = tsg_new.DAYD_EXT;
  old_DAYD = tsg_old.DAYD_EXT;
end

% If tsg_new.Para and tsg_old.Para are empty nothing is done
% ----------------------------------------------------------
if isempty(tsg_new.(Para)) && isempty(tsg_old.(Para))
  return;
  
  % If only tsg_new.PARA is empty, fill it with label. The dimension of the
  % final array must must be equal to the sum of the dimension of tsg.DAYD
  % and tsg_old.DAYD
  % ----------------------------------------------------------------------
elseif isempty(tsg_new.(Para))
    tsg_new.(Para) = label( ones(length(new_DAYD),1), :);
  
  % See preceding comment
  % ---------------------
elseif isempty(tsg_old.(Para))
    tsg_old.(Para) = label( ones(length(old_DAYD),1), :);
end

% Concatenation
% -------------
tsg_old.(Para) = strvcat(tsg_old.(Para), tsg_new.(Para));

% Re-order the struct array
% -------------------------
tsg_old.(Para) = tsg_old.(Para)(iOrder,:);

end

%% *************************************************************************
function tsg_old = concatInt8Tsg( iOrder, NO_CONTROL, tsg_old, tsg_new, Para)
%
% function concatInt8Tsg : Concatenate 2 numeric int8 arrays 
%
% Input
% iOrder - Indicies to organise the array in time ascending order
% NO_CONTROL - Value for no control quality code
% tsg_old - First TSG structure
% tsg_new - Second TSG structure
% Para - Member of the structures to concatenate
%
% Output
% tsg_old - TSG structure
%

% Detect if the variable Para is a TSG parameter or an EXT parameter
% Choose the right date
% ------------------------------------------------------------------
if isempty( strfind(Para, 'EXT') )
  new_DAYD = tsg_new.DAYD;
  old_DAYD = tsg_old.DAYD;
else
  new_DAYD = tsg_new.DAYD_EXT;
  old_DAYD = tsg_old.DAYD_EXT;
end

% If tsg_new.Para and tsg_old.Para are empty nothing is done
% ----------------------------------------------------------
if isempty(tsg_new.(Para)) && isempty(tsg_old.(Para))
  return;
  
% If only tsg.PARA is empty, fill it with NO_CONTROL. The dimension of the  
% concatenate array must must be equal to the sum of the dimension of 
% tsg.DAYD and tsg_old.DAYD
% --------------------------------------------------------------------
elseif isempty(tsg_new.(Para))
  tsg_new.(Para)      = int8(NO_CONTROL) * int8(ones( size( new_DAYD )));

% See preceding comment
% ---------------------
elseif isempty(tsg_old.(Para))
  tsg_old.(Para)  = int8(NO_CONTROL) * int8(ones( size( old_DAYD )));
end

% Concatenation
% -------------
tsg_old.(Para) = [tsg_old.(Para); tsg_new.(Para)];

% Re-order the struct array
% -------------------------
tsg_old.(Para) = tsg_old.(Para)(iOrder);

end

%% ************************************************************************
function tsg = supTsgDouble( tsg)
%
% function supTsgDouble : Suppress TSG measurements made at the same date
% The comparison cannot be made using tsg.DAYD :
% This cannot be done using the Matlab Serial Date format as there can be
% some loss of precision. Especially when a floating number was written in
% a file.
%
% I use tsg.DATE. Could be simplify by comparing string rather than
% converting DATE with datenum
%
% ------------------------------------------------------------------------

% Convert string array DATE in numerical array
% --------------------------------------------
date = str2num(tsg.DATE);

% Compare adjacent element in an array
% ------------------------------------
date_diff = find( diff( date ) == 0 );
if ~isempty( date_diff )
  tsg.DAYD(date_diff) = [];
  tsg.DATE(date_diff,:) = [];
  
  tsg.LATX(date_diff) = [];
  tsg.LONX(date_diff) = [];
  tsg.POSITION_QC(date_diff) = [];
  
  if ~isempty(tsg.SPDC); tsg.SPDC(date_diff) = []; end
  if ~isempty(tsg.PRES); tsg.PRES(date_diff) = []; end
  if ~isempty(tsg.FLOW); tsg.FLOW(date_diff) = []; end
  if ~isempty(tsg.CNDC); tsg.CNDC(date_diff) = []; end
  if ~isempty(tsg.CNDC_STD); tsg.CNDC_STD(date_diff) = []; end
  if ~isempty(tsg.CNDC_CAL); tsg.CNDC_CAL(date_diff) = []; end
  if ~isempty(tsg.CNDC_FREQ); tsg.CNDC_FREQ(date_diff) = []; end
  
  if ~isempty(tsg.SSJT); tsg.SSJT(date_diff) = []; end
  if ~isempty(tsg.SSJT_QC); tsg.SSJT_QC(date_diff) = []; end
  if ~isempty(tsg.SSJT_STD); tsg.SSJT_STD(date_diff) = []; end
  if ~isempty(tsg.SSJT_CAL); tsg.SSJT_CAL(date_diff) = []; end
  if ~isempty(tsg.SSJT_FREQ); tsg.SSJT_FREQ(date_diff) = []; end
  if ~isempty(tsg.SSJT_ADJUSTED); tsg.SSJT_ADJUSTED(date_diff) = []; end
  if ~isempty(tsg.SSJT_ADJUSTED_ERROR); tsg.SSJT_ADJUSTED_ERROR(date_diff) = []; end
  if ~isempty(tsg.SSJT_ADJUSTED_QC); tsg.SSJT_ADJUSTED_QC(date_diff) = []; end
  % if ~isempty(tsg.SSJT_ADJUSTED_HIST(date_diff,:) = []; end
  
  if ~isempty(tsg.SSPS); tsg.SSPS(date_diff) = []; end
  if ~isempty(tsg.SSPS_QC); tsg.SSPS_QC(date_diff) = []; end
  if ~isempty(tsg.SSPS_STD); tsg.SSPS_STD(date_diff) = []; end
  if ~isempty(tsg.SSPS_CAL); tsg.SSPS_CAL(date_diff) = []; end
  if ~isempty(tsg.SSPS_ADJUSTED); tsg.SSPS_ADJUSTED(date_diff) = []; end
  if ~isempty(tsg.SSPS_ADJUSTED_ERROR); tsg.SSPS_ADJUSTED_ERROR(date_diff) = []; end
  if ~isempty(tsg.SSPS_ADJUSTED_QC); tsg.SSPS_ADJUSTED_QC(date_diff) = []; end
  %  if ~isempty(tsg.SSPS_ADJUSTED_HIST(date_diff,:) = []; end
  
  if ~isempty(tsg.SSTP); tsg.SSTP(date_diff) = []; end
  if ~isempty(tsg.SSTP_QC); tsg.SSTP_QC(date_diff) = []; end
  if ~isempty(tsg.SSTP_CAL); tsg.SSTP_CAL(date_diff) = []; end
  if ~isempty(tsg.SSTP_FREQ); tsg.SSTP_FREQ(date_diff) = []; end
  if ~isempty(tsg.SSTP_ADJUSTED); tsg.SSTP_ADJUSTED(date_diff) = []; end
  if ~isempty(tsg.SSTP_ADJUSTED_ERROR); tsg.SSTP_ADJUSTED_ERROR(date_diff) = []; end
  if ~isempty(tsg.SSTP_ADJUSTED_QC); tsg.SSTP_ADJUSTED_QC(date_diff) = []; end
  % if ~isempty(tsg.SSTP_ADJUSTED_HIST);tsg.SSTP_ADJUSTED_HIST(date_diff,:) = []; end
end
end

%% ************************************************************************
function tsg = supTsgExtDouble(tsg)
%
% supTsgExtDouble : suppress EXT measurements made at the same date
% The comparison cannot be made using tsg.DAYD_EXT.
% This cannot be done using the Matlab Serial Date format as there can be
% some loss of precision.
%
% I use tsg.DATE_EXT
% ------------------------------------------------------------------------
if ~isempty( tsg.DATE_EXT )
  
  % Convert string array DATE in numerical array
  % --------------------------------------------
  date = str2num(tsg.DATE_EXT);
  
  % Compare adjacent element in an array
  % ---------------------------------------------
  date_diff = find( diff( date ) == 0 );
  
  if ~isempty( date_diff )
    tsg.DAYD_EXT(date_diff)           = [];
    tsg.DATE_EXT(date_diff,:)         = [];
    tsg.LATX_EXT(date_diff)           = [];
    tsg.LONX_EXT(date_diff)           = [];
    tsg.SSPS_EXT(date_diff)           = [];
    tsg.SSPS_EXT_QC(date_diff)        = [];
    tsg.SSPS_EXT_BOTTLE(date_diff,:)  = [];
    tsg.SSPS_EXT_TYPE(date_diff,:)    = [];
    tsg.SSPS_EXT_ANALDATE(date_diff,:)= [];
    tsg.SSTP_EXT(date_diff)           = [];
    tsg.SSTP_EXT_QC(date_diff)        = [];
    tsg.SSTP_EXT_TYPE(date_diff,:)    = [];
  end
  
end
end



