function return_status = nc_addvar ( ncfile, varstruct )
% NC_ADDVAR:  adds a variable to a NetCDF file
%
% USAGE:  status = nc_addvar ( ncfile, varstruct );
%
% PARAMETERS:
% Input
%    ncfile:
%    varstruct:
%        This is a structure with four fields:
%
%        Name
%        Nctype
%        Dimension
%        Attributes
%
%      "Name" is just that, the name of the variable to be defined.
%
%      "Nctype" should be 
%          'double', 'float', 'int', 'short', or 'byte', or 'char'
%          'NC_DOUBLE', 'NC_FLOAT', 'NC_INT', 'NC_SHORT', 'NC_BYTE', 'NC_CHAR'
%
%      "Dimension" is a cell array of dimension names.
%
%      "Attributes" is also a structure array.  Each element has two
%      fields, "Name", and "Value".
%
% Output: 
%     status:
%         -1 if the routine fails
%          0 is the routine succeeds
%
% AUTHOR:
%    johnevans@acm.org
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Name:  $
% $Id: nc_addvar.m,v 1.1 2005/06/29 16:07:00 brian Exp $
% AUTHOR:  johnevans@acm.org
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

return_status = -1;

if nargin < 2
	fprintf ( 2, '%s:  must have two input arguments.\n', mfilename );
	return
end


if ( ~strcmp(class(ncfile),'char') )
	fprintf ( 2, '%s:  1st input argument must be char.\n', mfilename );
	return
end

if ( ~isstruct(varstruct) )
	fprintf ( 2, '%s:  2nd input argument must be a structure.\n', mfilename );
	return
end

%
% Check that required fields are there.
% Must at least have a name.
if ~isfield ( varstruct, 'Name' )
	fprintf ( 2, '%s:  variable structure must at least have ''Name'' field.\n', mfilename );
	return
end

%
% Check that required fields are there.
% Default Nctype is double.
if ~isfield ( varstruct, 'Nctype' )
	varstruct.Nctype = 'double';
end

%
% Check that the datatype is known.
switch ( varstruct.Nctype )
case { 'NC_DOUBLE', 'double', ...
	'NC_FLOAT', 'float', ...
	'NC_INT', 'int', ...
	'NC_SHORT', 'short', ...
	'NC_BYTE', 'byte', ...
	'NC_CHAR', 'char'  }
	;
otherwise
	fprintf ( 2, '%s:  unknown Nctype ''%s''\n', mfilename, varstruct.Nctype );
	return
end

%
% Check that required fields are there.
% Default Dimension is none.  Singleton scalar.
if ~isfield ( varstruct, 'Dimension' )
	varstruct.Dimension = [];
end

%
% Check that required fields are there.
% Default Attributes are none
if ~isfield ( varstruct, 'Attribute' )
	varstruct.Attribute = [];
end

[ncid, status] = mexnc ( 'open', ncfile, 'write' );
if ( status < 0 )
	ncerr = mexnc ( 'strerror', status );
	fprintf ( 2, '%s:  mexnc:open failed on ''%s'', error message ''%s''.\n', mfilename, ncfile, ncerr );
	return
end

%
% determine the dimids of the named dimensions
num_dims = length(varstruct.Dimension);
dimids = [];
for j = 1:num_dims
	[dimids(j), status] = mexnc ( 'dimid', ncid, varstruct.Dimension{j} );
	if ( status < 0 )
		ncerr = mexnc ( 'strerror', status );
		mexnc ( 'close', ncid );
		strformat = '%s:  mexnc:dimid failed to return a dimid for %s, file %s, error ''%s''.\n';
		fprintf ( 2, strformat, mfilename, varstruct.Dimension{j}, ncfile, ncerr );
		return
	end
end


%
% go into define mode
status = mexnc ( 'redef', ncid );
if ( status < 0 )
	ncerr = mexnc ( 'strerror', status );
	mexnc ( 'close', ncid );
	fprintf ( 2, '%s:  mexnc:redef failed on %s, ''%s''.\n', mfilename, ncfile, ncerr );
	return
end

status = mexnc ( 'def_var', ncid, varstruct.Name, varstruct.Nctype, num_dims, dimids );
if ( status < 0 )
	ncerr = mexnc ( 'strerror', status );
	mexnc ( 'endef', ncid );
	mexnc ( 'close', ncid );
	fprintf ( 2, '%s:  mexnc:def_var failed on %s, ''%s''.\n', mfilename, ncfile, ncerr );
	return
end



status = mexnc ( 'endef', ncid );
if ( status < 0 )
	mexnc ( 'close', ncid );
	fprintf ( 2, '%s:  mexnc:redef failed on %s.\n', mfilename, ncfile );
	error ( msg );
end

status = mexnc ( 'close', ncid );
if ( status < 0 )
	fprintf ( 2, '%s:  mexnc:close failed on %s.\n', mfilename, ncfile );
	return;
end



%
% Now just use nc_attput to put in the attributes
for j = 1:length(varstruct.Attribute)
	attname = varstruct.Attribute(j).Name;
	attval = varstruct.Attribute(j).Value;
	status = nc_attput ( ncfile, varstruct.Name, attname, attval );
	if ( status == -1 )
		fprintf ( 2, '%s:  nc_attput failed to write %s to variable %s, file %s.\n', mfilename, attname, varstruct.Name, ncfile );
		return
	end
end

return_status = 0;
