function nc_add_recs ( ncfile, new_data, unlimited_dimension_name )
% NC_ADD_RECS:  add records onto the end of a netcdf file
%
% USAGE:  nc_add_recs ( ncfile, new_data, unlimited_dimension );
% 
% INPUT:
%   ncfile:  netcdf file
%   new_data:  Matlab structure.  Each field is a data array
%      to be written to the netcdf file.  Each array had
%      better be the same length.  All arrays are written
%      in the same fashion.
%   unlimited_dimension:
%      Optional.  Name of the unlimited dimension along which the data 
%      is written.  If not provided, we query for the first unlimited 
%      dimension (looking ahead to HDF5/NetCDF4).
%     
% OUTPUT:
%   None.  In case of an error, an exception is thrown.
%
% AUTHOR: 
%   johnevans@acm.org
%
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Id: nc_add_recs.m 1738 2006-08-29 15:30:09Z johnevans007 $
% $LastChangedDate: 2006-08-29 11:30:09 -0400 (Tue, 29 Aug 2006) $
% $LastChangedRevision: 1738 $
% $LastChangedBy: johnevans007 $
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


if nargin < 2
	error ( '%s:  need at least two input arguments.\n', mfilename );
end


%
% Check that we were given good inputs.
if ~isstruct ( new_data )
	error ( '%s:  2nd input argument must be a structure .\n', mfilename );
end

%
% Check that each field of the structure has the same length.
varnames = fieldnames ( new_data );
num_fields = length(varnames);
if ( num_fields <= 0 )
	error ( '%s:  2nd input cannot be an empty structure.\n', mfilename );
end
field_length = zeros(num_fields,1);
for j = 1:num_fields
	command = sprintf ( 'field_length(j) = size(new_data.%s,1);', varnames{j} );
	eval ( command );
end
if any(diff(field_length))
	error ( '%s:  Some of the fields do not have the same length.\n', mfilename );
end

%
% So we have this many records to write.
record_count(1) = field_length(1);


%
% Open netCDF file
%
[ncid,status ]=mexnc( 'open', ncfile, nc_nowrite_mode );
if status < 0
	ncerr = mexnc ( 'strerror', status );
	error ( '%s:  mexnc:open failed on %s, error message ''%s''\n', mfilename, ncfile, ncerr );
end



%
% If we were not given the name of an unlimited dimension, ask for it now.
if nargin < 3
	[unlimited_dimension_dimid, status] = mexnc ( 'inq_unlimdim', ncid );
	if status < 0
		ncerr = mexnc ( 'strerror', status );
		error ( '%s:  mexnc:inq_unlimdim failed on %s, error message ''%s''\n', mfilename, ncfile, ncerr );
	end

	if unlimited_dimension_dimid == -1
		fmt = '%s:  NetCDF file %s has no unlimited dimension.  Cannot write to it.\n';
		error ( fmt, mfilename, ncfile );
	end

	[unlimited_dimension_name, unlimited_dimension_length, status] = mexnc ( 'inq_dim', ncid, unlimited_dimension_dimid );
	if status < 0
		ncerr = mexnc ( 'strerror', status );
		fmt = '%s:  mexnc:inq_dim failed on %s, error message ''%s''\n';
		error ( fmt, mfilename, ncfile, ncerr );
	end
else
	
	%
	% Get the dimension info for the dimension we were given
	[unlimited_dimension_dimid, status] = mexnc ( 'inq_dimid', ncid, unlimited_dimension_name );
	if status < 0
		ncerr = mexnc ( 'strerror', status );
		fmt = '%s:  mexnc:inq_dimid failed, error message ''%s''\n';
		error ( fmt, mfilename, ncerr );
	end
	
	
	[unlimited_dimension_name, unlimited_dimension_length, status] = mexnc( 'inq_dim', ncid, unlimited_dimension_dimid );
	if status < 0
		ncerr = mexnc ( 'strerror', status );
		fmt = '%s:  mexnc:inq_dim failed, error message ''%s''\n';
		error ( fmt, mfilename, ncerr );
	end

end

%
% So we start writing here.
record_corner(1) = unlimited_dimension_length;

%
% For each field of "new_data" buffer, inquire as to the dimensions in the
% NetCDF file.  We need this data to properly tell nc_varput how to write
% the data
input_variable = fieldnames ( new_data );
num_vars = length(input_variable);
varsize = [];
for j = 1:num_vars
	dimsize = [];
	[varid, status] = mexnc('INQ_VARID', ncid, input_variable{j} );
	if ( status < 0 )
		mexnc('close',ncid);
		ncerr = mexnc ( 'strerror', status );
		fmt = '%s:  mexnc::inq_varid failed on %s, file %s, error message ''%s''.\n';
		error ( fmt, mfilename, input_variable{j}, ncfile, ncerr );
	end

	[dimids, status] = mexnc('INQ_VARDIMID', ncid, varid);
	if ( status < 0 )
		mexnc('close',ncid);
		ncerr = mexnc ( 'strerror', status );
		fmt = '%s:  mexnc::inq_vardimid failed on %s, %s, error message ''%s''.\n';
		error ( fmt, mfilename, input_variable{j}, ncfile, ncerr );
		error ( msg );
	end
	ndims = length(dimids);


	%
	% make sure that this variable is defined along the unlimited dimension.
	if ~any(find(dimids==unlimited_dimension_dimid))
		mexnc('close',ncid);
		format = '%s:  variable %s is not defined along dimension %s, not going to write anything.\n';
		error ( format, mfilename, input_variable{j}, unlimited_dimension_name );
	end

	for k = 1:ndims
		[dim_length, status] = mexnc('INQ_DIMLEN', ncid, dimids(k) );
		if ( status < 0 )
			mexnc('close',ncid);
			ncerr = mexnc ( 'strerror', status );
			format = '%s:  mexnc::inq_dimlen failed on dimid %d, variable %s, file %s, error message ''%s''.\n';
			error ( format, mfilename, dimid, input_variable{j}, ncfile, ncerr );
		end
		dimsize(k) = dim_length;
	end

	varsize.(input_variable{j}) = dimsize;

end

status = mexnc('close',ncid);
if status < 0 
	ncerr = mexnc ( 'strerror', status );
	fmt = '%s:  mexnc::close failed on %s, error message ''%s''.\n';
	error ( fmt, mfilename, ncfile, ncerr );
end




%
% write out each data field, as well as the minimum and maximum
for i = 1:num_vars

	current_var = input_variable{i};
	%fprintf ( 1, '%s:  processing %s...\n', mfilename, current_var );

	current_var_data = new_data.(current_var);
	var_buffer_size = size(current_var_data);

	netcdf_var_size = varsize.(current_var);

	corner = zeros( 1, length(netcdf_var_size) );
	count = ones( 1, length(netcdf_var_size) );

	corner(1) = record_corner(1);
	count(1) = record_count(1);


	
	for j = 2:length(var_buffer_size(:))
		if ( var_buffer_size(j) > 1 )
			count(j) = var_buffer_size(j);
		end
	end



	%
	% Ok, we are finally ready to write some data.
	nc_varput ( ncfile, current_var, current_var_data, corner, count );
   

end


return




