function error = headerForm(hTsgGUI)
%
% Input
% -----
% hTsgGUI ............ Handel to the main user interface
%
% Output
% ------
% error .............. 1: OK ; -1 : an error occured
%
% $Id$

%% TIPS:
% run headerForm:
% headerForm(findobj('Tag', 'TAG_TSG-QC_GUI'))

error = -1;

% Get the data from the application GUI
% -------------------------------------
tsg = getappdata(hTsgGUI, 'tsg_data');

% load platform mat file
% ----------------------
%load platform.mat;

% set default uicontrol size
% --------------------------
default_height = 0.03;
default_length = .11;

% Define uicontrol start position
% -------------------------------
left   = .01;
bottom = .95;
inc_x  =  2.2 * default_length;
inc_y  =  0.01;

% get actual date to format
% -------------------------
date = datestr(now, tsg.preference.date_format_attribute);

% Get an instance of dynaload objetc from file 'tsgqc_netcdf.csv'
% -----------------------------------------------------------------
nc      = dynaload('tsgqc_netcdf.csv');

% Get attributes & variables list from dynaload instance
% ------------------------------------------------------
nca_keys = keys(nc.ATTRIBUTES);
%ncv_keys = keys(nc.VARIABLES);

% set additionals variables, location may be change in the future
% ---------------------------------------------------------------
add_var = { 'SSPS_DEPH', 'SSPS_DEPH_MIN', 'SSPS_DEPH_MAX', ...
  'SSTP_DEPH', 'SSTP_DEPH_MIN', 'SSTP_DEPH_MAX'};

% set additionals variables, location may be change in the future
% ---------------------------------------------------------------
add_coeff_var = { 'SSJT_CALCOEF', 'SSJT_LINCOEF', 'CNDC_CALCOEF', ...
  'CNDC_LINCOEF', 'SSTP_CALCOEF', 'SSTP_LINCOEF'};

% if tsg_platform_info.csv not exist, create it
% ---------------------------------------------
existPlatform(hTsgGUI);

% % check if .ini file exist in data
% % --------------------------------
% file_ini = strcat(tsg.file.name, '.ini');

% Load platform_info object from tsg_platform_info.csv
% ----------------------------------------------------
platform_info = tsg_nc('tsg_platform.csv');

% % check if filename exist and should be open in read mode
% % -------------------------------------------------------
% file_ini_id = fopen(file_ini, 'r');
% if (file_ini_id ~= -1)
%   read_ini_file;
% end

% header Uicontrols in a new figure
% comment   'WindowStyle', 'modal', ... in debug mode
% ---------------------------------------------------
hHeaderFig = figure(...
  'BackingStore','off',...
  'Name', 'TSG GLOBAL ATTRIBUTES AND VARIABLES', ...
  'NumberTitle', 'off', ...
  'Resize', 'on', ...
  'Menubar','none', ...
  'Toolbar', 'none', ...
  'Tag', 'GLOBAL_ATTRIBUTES', ...
  'Visible','on',...
  'Units', 'normalized',...
  'Position',get(hTsgGUI,'Position'), ...
  'Color', get(0, 'DefaultUIControlBackgroundColor'));
%'WindowStyle', 'modal', ...
% bg = [0.92549 0.913725 0.847059] = get(0, 'DefaultUIControlBackgroundColor');

% Iterate from each element from object nca and additional variables
% ------------------------------------------------------------------
for i = nca_keys
  
  % get key, use char because i is cell
  % -----------------------------------
  key = char(i);
  
  % get all structure for the key
  % -----------------------------
  s = nc.ATTRIBUTES.(key);
  
  % check for empty field and replace them by default value
  % -------------------------------------------------------
  %   if isempty(s.length), s.length = default_length; end;
  %   if isempty(s.height), s.height = default_height; end;
  s.length = default_length;
  s.height = default_height;
  
  % display dynamically uicontrol text
  % use of char function to prevent error when field is empty [] => ''
  % ------------------------------------------------------------------
  uicontrol(...
    'Parent', hHeaderFig, ...
    'Units', 'normalized', ...
    'Style', 'Text', ...
    'Fontsize', tsg.fontSize-1, ...
    'HorizontalAlignment', 'left', ...
    'Position',[left, bottom, s.length, s.height], ...
    'TooltipString', char(s.comment), ...
    'String', char(s.name));
  
  % display dynamically uicontrol
  % -----------------------------
  ui = uicontrol(...
    'Parent', hHeaderFig, ...
    'Units', 'normalized', ...
    'BackgroundColor', 'w', ...
    'Style', char(s.uicontrolType), ...
    'Fontsize', tsg.fontSize-2, ...
    'HorizontalAlignment', char(s.horizontalAlignment), ...
    'Position', [left + s.length, bottom, s.length, s.height], ...
    'String', char(s.string), ...
    'Value', s.value, ...
    'Tag', key);
  
  % display conventions field if exist
  % ----------------------------------
  convention = char(s.conventions);
  name = char(s.name);
  
  % if attribute as a column conventions in csv file
  % ------------------------------------------------
  if ~isempty(convention)
    
    % get it
    % ------
    if ~isempty(strfind(name, 'DATE'))
      convention = tsg.preference.date_format_attribute;
    end
    
    % and display in text field
    % -------------------------
    uicontrol(...
      'Parent', hHeaderFig, ...
      'Units', 'normalized', ...
      'Style', 'text', ...
      'Fontsize', tsg.fontSize-4, ...
      'HorizontalAlignment', 'left', ...
      'Position', [left , bottom - (inc_y * 5/3), s.length, s.height], ...
      'String', strcat('[', convention, ']'));
  end
  
  % set dynamically uicontrol from tsg struct
  % -----------------------------------------
  switch s.uicontrolType
    
    % for a popmenu control, set index position
    % ---------------------------------
    case 'popupmenu'
      str = cellstr(get(ui,'String'));
      % ind = strfind(str,tsg.(key));
      
      % replace the + in pattern by \+, ex: 2B+ -> 2B\+
      pattern = regexprep(tsg.(key), '\+', '\\+');
      
      % use a regexp to find whole word instead of strfind
      ind = regexp(str, strcat('^', pattern, '$'), 'tokens');
      for k=1:numel(ind)
        if ~isempty(ind{k})
          set(ui, 'value', k);
        end
      end
      
      % for edit control, set uicontrol with tsg.(key) value
      % ----------------------------------------------------
    case 'edit'
      
      % if value empty or equal to N/A, display N/A in red
      % --------------------------------------------------
      if isempty(tsg.(key)) || strcmp(tsg.(key), 'N/A')
        set(ui, 'string', 'N/A', 'ForegroundColor', 'r');
      else
        set(ui, 'string', tsg.(key));
      end
      
      % for checkbox control, not yet implemented
      % ------------------------------------------
    case 'checkbox'
      % not yet implemented !!!
  end
  
  % Check vertical position of last uicontrol and creation new colomn
  % -----------------------------------------------------------------
  bottom = bottom - inc_y - s.height;
  if bottom < .1
    bottom = 0.95;
    left = left + inc_x;
  end
end

% additionnal variable here
% -------------------------
add_variables;

% additionnal coefficient variable here
% ------------------------------------
%if ~isempty(tsg.SSJT_CALCOEF)
add_coefficients;
%end

% set a callback to PLATFORM_NAME uicontrol
% -----------------------------------------
%set(findobj('Tag', 'PLATFORM_NAME'), 'Callback', @updateForm);

% set a callback to check date
% ----------------------------
set(findobj('-regexp', 'Tag', 'CALCOEF_DATE'), 'Callback', @editCallback);

% CONTINUE PUSH BUTTON
% --------------------
% The Continue (valid)  button
uicontrol( ...
  'Parent', hHeaderFig, ...
  'Style','pushbutton',...
  'Fontsize', tsg.fontSize,...
  'Units', 'normalized', ...
  'Position',[.01, .01, .1, .04],...
  'String','Continue',...
  'Interruptible','off',...
  'BusyAction','cancel',...
  'Tag','PUSH_BUTTON',...
  'Callback', @continueCallback);

% CANCEL PUSH BUTTON
% ------------------
% The cancel  button
uicontrol( ...
  'Parent', hHeaderFig, ...
  'Style','pushbutton',...
  'Fontsize', tsg.fontSize,...
  'Units', 'normalized', ...
  'Position',[.2, .01, .1, .04],...
  'String','Cancel',...
  'Interruptible','off',...
  'BusyAction','cancel',...
  'Tag','PUSH_BUTTON',...
  'Callback', @cancelCallback);

% Build structure container for graphic handles with tag property defined.
% ------------------------------------------------------------------------
data = guihandles(hHeaderFig);

% record data struct in application data object
% ---------------------------------------------
% guidata(hHeaderFig, data);

% stop execution until push-button Continue was press
% ---------------------------------------------------
uiwait(hHeaderFig);

%% Nested callback

% -----------------------------------------------------------------------
% check if date format is valid, if not beep and set empty string
% -----------------------------------------------------------------------
  function editCallback(obj, event)
    value = get(obj, 'string');
    match = regexp( value, '^(\d{4})(\d{2})(\d{2})$', 'match');
    if isempty(match)
      beep;
      set(obj, 'string', '');
    end
  end

% -----------------------------------------------------------------------
% Continue action, get uicontrol fields and populate tsg structure
% -----------------------------------------------------------------------
  function continueCallback(obj, event)
    
    % get the PLATFORM_NAME value, use tag to retrieve
    % ------------------------------------------------
    platform_name = get(findobj('Tag', 'PLATFORM_NAME'), 'string');
    
    % get platform info structure from hashtable store in platform_info object
    % ------------------------------------------------------------------------
    p_i = get(platform_info, platform_name);
    
    % get hashtable describing platform_info structure data type
    % ----------------------------------------------------------
    hdr = header(platform_info);
    
    % Iterate from each element from object nca + additional variables
    % ----------------------------------------------------------------
    for ncak = nca_keys
      
      % get key, use char for cell ncak
      % ----------------------------
      key = char(ncak);
      
      % get all structure for the key, for additional variables, s = {}
      % --------------------------------------------------------------
      s = nc.ATTRIBUTES.(key);
      
      % get the corresponding string from uicontrol using guihandles
      % data (dynamic)
      % ------------------------------------------------------------
      tsg.(key) = get(data.(key), 'string');
      
      % set tsg.DATE_UPDATE
      % -------------------
      if strcmp(key, 'DATE_UPDATE')
        tsg.(key) = date;
      end
      
      % if uicontrol is a popupmenu, string is cell array with all choices
      % ------------------------------------------------------------------
      if ~isempty(s) && strcmp(s.uicontrolType,'popupmenu')
        
        % get the corresponding string from cell array  using selected value
        % ------------------------------------------------------------------
        tsg.(key) = deblank(tsg.(key)(get(data.(key), 'value'),:));
        
        % set tsg.CONVENTIONS and FORMAT_VERSION to the latest default
        % version in tsgqc_netcdf.csv value
        % -----------------------------------------------------------
        if strcmp(key, 'CONVENTIONS') || strcmp(key, 'FORMAT_VERSION')
          default_value = nc.ATTRIBUTES.(key).value;
          popup_value = get(data.(key), 'string');
          tsg.(key) = deblank(popup_value(default_value,:));
        end
        
      end
      
      
      
      % update p_i structure from tsg only with corresponding field
      % -----------------------------------------------------------
      if isfield(p_i, key)
        
        % get data type from platform_info structure
        % ------------------------------------------
        switch hdr.(key)
          case 'char'
            p_i.(key) = tsg.(key);
          case 'byte'
            p_i.(key) = int8(str2double(tsg.(key)));
          case 'integer'
            p_i.(key) = int16(str2double(tsg.(key)));
          case 'float'
            p_i.(key) = single(str2double(tsg.(key)));
          case 'double'
            p_i.(key) = str2double(tsg.(key));
          otherwise
            
            % by default, display a warning
            % -----------------------------
            warning('tsgqc:headerForm', ...
              'unknow type ''%s'' for ''%s'' attribute.\nCheck your %s file', ...
              hdr.(key), key, platform_info.file);
            
            % and cast to char
            % ----------------
            p_i.(key) = tsg.(key);
        end
      end
    end
    
    % get additional variables from uicontrol and update tsg struct
    % -------------------------------------------------------------
    for kk =  add_var
      key = char(kk);
      tsg.(key) = str2double(get(data.(key), 'string'));
      p_i.(key) = tsg.(key);
    end
    
    % get additional coefficients from uicontrol and update tsg struct
    % ----------------------------------------------------------------
    if ~isempty(tsg.SSJT_CALCOEF)
      for kk =  add_coeff_var
        var = char(kk);
        for ii=1:numel(tsg.(var))
          key = strtrim(tsg.([var '_CONV'])(ii,:));
          if strcmpi(key, '')
            continue
          end
          s = get(data.(strcat(var,'_',key)), 'string');
          %tsg.(var)(i) = single(str2double(get(data.(strcat(var,'_',key)), 'string')));
          
          if strcmp(s, '')
            tsg.(var)(ii) = NaN;
          else
            if strcmpi(key, 'DATE')
              tsg.(var)(ii) = double(datenumToJulian(datenum(s, 'yyyymmdd')));
            else
              tsg.(var)(ii) = double(str2double(s));
            end
          end
          %p_i.(key) = tsg.(key);
        end
      end
    end
    
    
    % Save tsg structure
    % ------------------
    setappdata(hTsgGUI, 'tsg_data', tsg);
    
    % test if uicontrol not empty
    % ---------------------------
    if isempty(platform_name)
      warndlg({'PLATFORM NAME is empty';'';'Please, enter a valid PLATFORM name'},...
        'Invalid PLATFORM name');
    else
      
      % Update plateform_info object with this PLATFORM_NAME value and
      % platform info updated structure
      % --------------------------------------------------------------
      platform_info = set(platform_info, platform_name, p_i);
      
      % save object in csv file
      % -----------------------
      save(platform_info);
      
      % close windows (replace call to uiresume(hHeaderFig))
      % ----------------------------------------------------
      close(hHeaderFig);
      
      % flushes the event queue and updates the figure window
      % -----------------------------------------------------
      drawnow;
      
      % return with no error code (true)
      % --------------------------------
      error = 1;
      return
      
    end
    
  end % end of continueCallback nested function

% -----------------------------------------------------------------------
% Cancel button, no action
% -----------------------------------------------------------------------
  function cancelCallback(obj, event)
    
    % close windows
    % -------------
    close(hHeaderFig);
    
    % flushes the event queue and updates the figure window
    % -----------------------------------------------------
    drawnow;
    
    % return error code (no change)
    % -----------------------------
    error = -1;
    
  end % end of cancelCallback nested function

% -----------------------------------------------------------------------
% Callback when uicontrol PLATFORM_NAME is modified
% -----------------------------------------------------------------------
  function updateForm(obj, event)
    
    % get the new value, use tag to retrieve
    % --------------------------------------
    platform_name = get(findobj('Tag', 'PLATFORM_NAME'), 'string');
    
    % get platform info structure from hashtable store in platform_info object
    % ------------------------------------------------------------------------
    p_i = get(platform_info, platform_name);
    
    % get hashtable describing platform_info structure data type
    % ----------------------------------------------------------
    %hdr = header(platform_info);
    
    % if this platform exist, structure not empty
    % -------------------------------------------
    if ~isempty(p_i)
      
      % iterate on all members of platform_info structure, filenames return
      % a cell array of string
      % -------------------------------------------------------------------
      nb = fieldnames(p_i);
      
      for ii = 1:numel(nb)
        
        % convert each cell to char
        % -------------------------
        key = nb{ii};
        
        % update tsg with data from platform_info struct
        % TODOS:
        % may be add color test here
        % ----------------------------------------------
        tsg.(key) = p_i.(key);
        
        % get uicontrol style
        % -------------------
        type = get(data.(key), 'style');
        
        % update headerform fields
        % ------------------------
        switch type
          case 'edit'
            set(data.(key), 'string', tsg.(key));
          case 'popupmenu'
            indice = strmatch(tsg.(key), get(data.(key), 'string'));
            set(data.(key), 'value', indice);
        end
        
        
        % with different color
        % --------------------
        set(findobj('Tag', key), 'foregroundColor', 'r');
        
      end
      
      % if user enter a new PLATFORM_NAME, open a question dialog box for
      % confirmation
      % -----------------------------------------------------------------
    else
      selection = ...
        questdlg(['PLATFORM NAME: ' platform_name ' is new.  Do you want to use and save it ?'],...
        'Create new PLATFORM NAME ?',...
        'Yes', 'No', 'No');
      
      % if yes, continue, create and save new hash for PLATFORM_NAME in csv file
      % ------------------------------------------------------------------------
      if strcmp(selection, 'Yes')
        return;
        
        % if not, reset field
        % -------------------
      else
        set(findobj('Tag','PLATFORM_NAME'),'string', '');
      end
    end
    
  end % end of updateForm nested function

% additionnal variable here
% -------------------------
  function add_variables
    
    % get the PLATFORM_NAME value, use tag to retrieve
    % ------------------------------------------------
    platform_name = get(findobj('Tag', 'PLATFORM_NAME'), 'string');
    
    % get platform info structure from hashtable store in platform_info object
    % ------------------------------------------------------------------------
    p_i = get(platform_info, platform_name);
    
    % display dynamically uicontrol text over add_var list
    % ----------------------------------------------------
    for ad = add_var
      
      key = char(ad);
      
      uicontrol(...
        'Parent', hHeaderFig, ...
        'Units', 'normalized', ...
        'Style', 'Text', ...
        'Fontsize', tsg.fontSize-1, ...
        'HorizontalAlignment', 'left', ...
        'Position',[left, bottom, s.length, s.height], ...
        'TooltipString', '', ...
        'String', key);
      
      ui = uicontrol(...
        'Parent', hHeaderFig, ...
        'Units', 'normalized', ...
        'BackgroundColor', 'w', ...
        'Style', 'edit', ...
        'Fontsize', tsg.fontSize-2, ...
        'HorizontalAlignment', 'right', ...
        'Position', [left + s.length, bottom, s.length, s.height], ...
        'String', '', ...
        'Tag',  key);
      
      % Check vertical position of last uicontrol and creation new colomn
      % -----------------------------------------------------------------
      bottom = bottom - inc_y - s.height;
      if bottom < .1
        bottom = 0.95;
        left = left + inc_x;
      end
      
      
      % update uicontrol from tsg structure or plateform_info
      % -----------------------------------------------------
      if isempty( tsg.(key) )
        
        % get value from platform_info
        % ----------------------------
        if ~isempty(p_i)
          set(ui, 'string', p_i.(key));
        end
      else
        set(ui, 'string', tsg.(key));
      end
    end
  end % end of add_variables nested function

% additionnal coefficients variable here
% --------------------------------------
  function add_coefficients

    % display dynamically uicontrol text over add_var list
    % ----------------------------------------------------
    for acv = add_coeff_var
      
      % get key from cell array of keys
      % ------------------------------
      var = char(acv);
      
      % check before use, if variable has the right vertical dimensions
      % if not, write fillValue: NaN or char filled with blanks
      % ------------------------------------------------------------
      match = regexp(var, '\w+_(\w+)', 'tokens');
      for ii=numel(tsg.(var))+1:tsg.dim.(char(match{1}))
        tsg.(var)(ii) = NaN;
        tsg.([var '_CONV'])(ii,:) = padding('', tsg.dim.COEF_CONV_SIZE);
      end
      
      % loop for each value of coefficient variable
      % -------------------------------------------
      for ii=1:numel(tsg.(var))
        tsg.([var '_CONV']);
        cle = tsg.([var '_CONV'])(ii,:);
        
        % if fillValue, don't display uicontrol
        % -------------------------------------
        if strcmp(cle, padding('', tsg.dim.COEF_CONV_SIZE))
          continue
        end
        
        % if key is date, use special format, not real
        % --------------------------------------------
        if isnan(tsg.(var)(ii))
          value = '';
        elseif strcmpi(cle, padding('DATE', tsg.dim.COEF_CONV_SIZE))
          value = datestr(julianToDatenum(tsg.(var)(ii)), 'yyyymmdd');
        else
          value = num2str(tsg.(var)(ii),'%10.8e');
        end
        
        % concate variable name with key: eg SSJT_CALCOEF_H
        % -------------------------------------------------
        cle = strcat(var, '_', cle);
        
        % display iucontrol
        % -----------------
        uicontrol(...
          'Parent', hHeaderFig, ...
          'Units', 'normalized', ...
          'Style', 'Text', ...
          'Fontsize', tsg.fontSize-1, ...
          'HorizontalAlignment', 'left', ...
          'Position',[left, bottom, s.length, s.height], ...
          'TooltipString', '', ...
          'String', cle);
        
        uicontrol(...
          'Parent', hHeaderFig, ...
          'Units', 'normalized', ...
          'BackgroundColor', 'w', ...
          'Style', 'edit', ...
          'Fontsize', tsg.fontSize-2, ...
          'HorizontalAlignment', 'right', ...
          'Position', [left + s.length, bottom, s.length, s.height], ...
          'String', value, ...
          'Tag', char(cle) );
        
        % add convention for <PARAM>_CALCOEF_DATE
        % ---------------------------------------
        if ~isempty(strfind(cle, 'CALCOEF_DATE'))
          uicontrol(...
            'Parent', hHeaderFig, ...
            'Units', 'normalized', ...
            'Style', 'text', ...
            'Fontsize', tsg.fontSize-4, ...
            'HorizontalAlignment', 'left', ...
            'Position', [left , bottom - (inc_y * 5/3), s.length, s.height], ...
            'String', '[yyyymmdd]');
        end
        
        % Check vertical position of last uicontrol and creation new colomn
        % -----------------------------------------------------------------
        bottom = bottom - inc_y - s.height;
        if bottom < .1
          bottom = 0.95;
          left = left + inc_x;
        end
        
      end
      
    end
  end % end of add_variables nested function

end % end of headerForm

