function [error] = writeTSGDataNetCDF( hTsgGUI, filename)
% [error] = writeTSGDataNetCDF( hTsgGUI, filename)
% Function to write TSG data in NetCDF file to GOSUD format 1.6.
%
% Input
% -----
% hTsgGUI ............ Handle to the main user interface
% filename ........... Data filename
%
% Output
% ------
% error .............  1 : OK
%       ............. -1 : an error occured
%
% The data are store using setappdata - Variable name : 'tsg_data'
%
% DAYD, DAYD_WS and DAYD_EXT in tsg structure use Matlab datenum, they 
% should be converted to julian days using 1950 reference in NetCDF file 
%
% $Id$

%% Check Netcdf library version
% -----------------------------
switch ( version('-release') )
  case { '11', '12', '13', '14', '2006a', '2006b', '2007a', '2007b', '2008a' }
    write_netcdf_toolbox;
  otherwise
    write_netcdf_native;
end

%% Nested functions
% -----------------

% use Charles Dunham toolbox
% --------------------------
  function write_netcdf_toolbox
    
    
    %% Open the file
    % --------------
    nc = netcdf(filename, 'clobber');
    if isempty(nc)
      msg_error = ['TSG_GOSUD file_lecture : Open file error : ' filename];
      warndlg( msg_error, 'NetCDF write dialog');
      error = -1;
      return;
    end
    
    % Display read file info on console
    % ---------------------------------
    fprintf('\nWRITE_NETCDF_FILE\n'); tic;
    
    % Initialize loading NetCDF file waitbar
    % --------------------------------------
    wb = waitbar(0, 'Initializing NetCDF file. Please  wait...');
    
    % We cannot change title property to 'none' (default set as 'tex') inside
    % waitbar function (line 81), see
    % http://www.mathworks.co.uk/matlabcentral/newsreader/view_thread/115725
    % -----------------------------------------------------------------------
    hchild = get(wb,'children');
    htitle = get(hchild,'title');
    set(htitle,'Interpreter','None');
    
    % Get the data from the application GUI
    % -------------------------------------
    tsg = getappdata( hTsgGUI, 'tsg_data');
    
    % Get an instance of dynaload objetc from file 'tsgqc_netcdf.csv'
    % -----------------------------------------------------------------
    dyna = dynaload('tsgqc_netcdf.csv');
    
    % Get attributes & variables list from dynaload instance
    % ------------------------------------------------------
    ncd_keys = keys(dyna.DIMENSIONS);
    ncv_keys = keys(dyna.VARIABLES);
    nca_keys = keys(dyna.ATTRIBUTES);
    
    %ncv_fieldNames  = get_fieldnames(ncv);
    
    % Display more info about write file on console
    % ---------------------------------------------
    fprintf('...writing %s : ', filename);
    
    %% Create NetCDF file:
    % -------------------
    % for key = ncd_keys
    %   k = char(key);
    %   value = dyna.DIMENSIONS.(key).value;
    %   if ~isempty(value)
    %     nc(k) = value;
    %   elseif ~isempty(tsg.(k))
    %     nc(k) = numel(tsg.(k));
    %   end
    % end
    
    % Variable dimensions
    % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    % pour l'instant, code en dur, a revoir !!!!!!!!!!!!!!!!
    % -------------------
    nc('DAYD')      = numel(tsg.DAYD);
    
    % if dimension is empty (no data), don't create, because create empty
    % dimension quive it unlimited dimension, but you can only have one
    % unlimited dimension in a file
    % --------------------------------------------------------------------
    
    % number of external SSPS or SSTP comparison
    % ------------------------------------------
    if ~isempty(tsg.DAYD_EXT)
      nc('DAYD_EXT')  = numel(tsg.DAYD_EXT);
    end
    
    % number of calibration coefficients
    % ----------------------------------
    nc('NCOEF_CAL') = tsg.dim.CALCOEF;   % 7
    
    % number of linearisation coefficients
    % ------------------------------------
    nc('NCOEF_LIN') = tsg.dim.LINCOEF;   % 2
    
    % Fixed dimensions
    % ----------------
    nc('STRING256') = tsg.dim.STRING256;
    nc('STRING16')  = tsg.dim.STRING16;
    nc('STRING14')  = tsg.dim.STRING14;
    nc('STRING8')   = tsg.dim.STRING8;
    nc('STRING4')   = tsg.dim.STRING4;
    nc('N1')        = tsg.dim.N1;
    
    % display filename after 'Interpreter','None' initialization to prevent
    % display console warning
    % ---------------------------------------------------------------------
    waitbar(1/50,wb,['Writing file: ' filename ' Please  wait...']);
    
    %% Create NetCDF global attributes
    % -------------------------------
    for key = nca_keys
      global_att = char(key);
      nc.(global_att) = tsg.(global_att);
    end
    
    % Create NetCDF variables and attributes
    % --------------------------------------
    for key = ncv_keys
      
      variable = char(key);
      
      % get structure
      % -------------
      s = dyna.VARIABLES.(variable);
      
      ncv_fieldNames  = fieldnames(s);
      
      % get variable dimension declare in file
      % --------------------------------------
      %dimension = get(ncv, variable, ncv_fieldNames{1});
      dimension = s.dimension__;
      
      % get variable type declare in file
      % --------------------------------------
      %nctype    = get(ncv, variable, ncv_fieldNames{2});
      nctype = s.type__;
      
      % create netcdf variable with dimension, dimension must be a cell
      % ---------------------------------------------------------------
      switch nctype
        case 'double'
          nc{variable} = ncdouble(dimension);
        case 'float'
          nc{variable} = ncfloat(dimension);
        case 'int'
          nc{variable} = ncint(dimension);
        case 'short'
          nc{variable} = ncshort(dimension);
        case 'byte'
          nc{variable} = ncbyte(dimension);
        case 'char'
          nc{variable} = ncchar(dimension);
        otherwise
          % by default, display a warning and cast to char
          % ----------------------------------------------
          warning('tsgqc_GUI:writeTSGDataNetCDF', ...
            'unknow type ''%s'' for  dimension ''%s'' of  ''%s'' variable.\nCheck your %s file', ...
            nctype, dimension{1}, variable, file(ncv));
          
          nc{variable} = ncchar(dimension);
      end
      
      % create variable attribute, jump dimension and nctype fields
      % -----------------------------------------------------------
      for j=1:numel(ncv_fieldNames)
        
        % see new us191.netcdf toolbox, we'll not use index to get type
        % but structure with special variable, eg: s.type__
        % -------------------------------------------------
        fieldName = ncv_fieldNames{j};
        value     = s.(fieldName);
        %nctype    = get(ncv, variable, ncv_fieldNames{2});
        
        % jump each internal fieldname (eg key__, data__, type__, dimension__)
        % or empty fieldname
        % -------------------------------------------------------------
        if ~isempty(regexp(fieldName, '__$','ONCE')) || isempty(value)
          continue;
        end
        
        % if field is empy, it's not a attribute for this netcdf variable
        % ---------------------------------------------------------------
        if ~isempty(value)
          
          % ncatt(theAttname, theAttvalue, theParent) uses the class of
          % theAttvalue as theAtttype ('char' or 'double').
          % need to be cast before assignment
          % -----------------------------------------------------------
          if isnumeric(value)
            
            % BE CAREFUL
            % bug dans la toolbox, le cast autre que double met l'attribut a 0
            % keep these lines comment !!!!!!!!!!!!
            
            %          switch nctype
            %              case {'double', 'real', 'float', 'single'}
            %                value = double(value);
            %              case {'float', 'single'}
            %                value = single(value);
            %             case {'int', 'integer', 'int32'}
            %               value = int32(value);
            %             case {'short', 'int16'}
            %               value = int16(value);
            %             case 'int8'
            %               value = int8(value);
            %             % bug dans la toolbox, le type uint ne marche pas
            %             % on met int8
            %             case {'byte', 'uint8'}
            %               value = int8(value);
            %           end
            nc{variable}.(fieldName) = value;
            
          else
            nc{variable}.(fieldName) = char(value);
          end
          
        end
      end
    end
    
    %% Create data to NetCDF file:
    % ---------------------------
    
    % Write global attributes
    % -----------------------
    for i=1:numel(nca_keys)
      
      % get netcdf global attribute name
      % --------------------------------
      global_attr = nca_keys{i};
      
      nc.(global_attr) = tsg.(global_attr);
    end
    
    % Convert Matlab julian days (datenum) to 1950 reference
    % ------------------------------------------------------
    d = strmatch('DAYD',ncv_keys);
    for i=1:numel(d)
      tsg.(ncv_keys{d(i)}) = datenumToJulian(tsg.(ncv_keys{d(i)}));
    end
    
    % shift to [-180 180] longitude range if needed
    % ---------------------------------------------
    if ~isempty(tsg.indcross)
      tsg.LONX = mod(tsg.LONX+180,360)-180;
    end
    
    % Write measurements (tsg.variables)
    % ----------------------------------
    for i=1:numel(ncv_keys)
      
      % get netcdf variable name
      % ------------------------
      variable = ncv_keys{i};
      
      % display waitbar
      % ---------------
      waitbar( i/numel(ncv_keys), wb, ['writing ' variable ' variable']);
      
      % get ncvar type object nv
      % ------------------------
      nv = nc{variable};
      
      % be careful, if dimension DAYD_EXT not defined (no sample data),
      % nv is empty
      % ---------------------------------------------------------
      if ~isempty(nv)
        
        % set autonan mode (FillValue_)
        % -----------------------------
        nv = autonan(nv,1);
        
        % tsg variable is not empty, fill nv with it
        % ------------------------------------------
        if ~isempty(tsg.(variable))
          
          % fill netcdf variables nv with corresponding tsg variable
          % --------------------------------------------------------
          nv(:) = tsg.(variable);
          
          % In case of unlimited dimension, for example only, use:
          % nc{variable}(1:length(tsg.(variable))) = tsg.(variable)
          % -------------------------------------------------------
          
        else
          
          % if default_value defined, fill nv with it
          % -----------------------------------------
          if ~isempty(nv.default_value(:))
            % a verifier, doit marcher pour tout les type de variable
            %nv(:) = int8(nv.default_value(:));
            nv(:) = nv.default_value(:);
          end
          
        end
        
      end
      
    end % end of loop over variables keys
    
    % Close waitbar
    % -------------
    close(wb)
    
    % Close NetCDF file
    % -----------------
    endef(nc)
    close(nc)
    
    % Display time to write file on console
    % -------------------------------------
    t = toc; fprintf('...done (%6.2f sec).\n\n',t);
    
    % Everything OK
    % -------------
    error = 1;
    
  end % end of nested function nc_write_old

% use native toolbox +netcdf since R2008b
% ---------------------------------------
  function write_netcdf_native
    
    % Get the data from the application GUI
    % -------------------------------------
    tsg = getappdata( hTsgGUI, 'tsg_data');
    
    % shift to [-180 180] longitude range if needed
    % ---------------------------------------------
    if ~isempty(tsg.indcross)
      tsg.LONX = mod(tsg.LONX+180,360)-180;
    end
    
    % Get an instance of dynaload object from file 'tsgqc_netcdf.csv'
    % -----------------------------------------------------------------
    nc = netcdf_native('tsgqc_netcdf.csv');
    
    % loop over all variables and get associated value in tsg structure
    % -----------------------------------------------------------------
    for key = keys(nc.VARIABLES)
      var = char(key);
      
      % Convert Matlab julian days (datenum) to 1950 reference
      % ------------------------------------------------------
      if strmatch('DAYD', var)
        nc.VARIABLES.(var).data__ = datenumToJulian(tsg.(var));
      else
        nc.VARIABLES.(var).data__ = tsg.(var);
      end
    end
    
    % loop over all global attributes and get associated value in tsg
    % structure
    % -----------------------------------------------------------------
    for key = keys(nc.ATTRIBUTES)
      att = char(key);
      nc.ATTRIBUTES.(att).data__ = tsg.(att);
    end
    
    % write netcdf file with and display waibar (boolean)
    % ---------------------------------------------------
    write( nc, filename, 'NC_CLOBBER', true );
    
    % Everything OK
    % -------------
    error = 1;
    
  end

end % end od writeTSGDataNetCDF

