function nc_varput(ncfile , varname , vardata , varargin )
%
% version of nc_varput for mexec to replace snctools version
% the aim is to replace snctools nc_ calls with faster versions that make
% simple native matlab netcdf calls.
%
% rather than changing every mexec program, the snctools library can be
% replaced with this library
%
% varargin can be
% start, count, stride
% start begins at zero, so if start = [2 3] it will retrieve data from
% row 3, column 4;
% if start is defined and count is empty, the data are retrieved from
% the point denoted by the start offset, to the end of each row and column.
%
% If subsetting is used, ie start, count, stride, then the size of vardata
% must exactly match the number of elements implied by the subsetting.
% There is no checking that this matches, the program will just crash if it
% things don't match.
%
% When I tried it, the -1 notation for count in the snctools version did
% not work as intended.
%
% This version handles _FillValue but not missing values or scaling or
% offset.
%
% The old snctools description was
%
% % NC_VARPUT:  Writes data into a netCDF file.
% %
% % NC_VARPUT(NCFILE,VARNAME,DATA) writes the matlab variable DATA to
% % the variable VARNAME in the netCDF file NCFILE.  The main requirement
% % here is that DATA have the same dimensions as the netCDF variable.
% %
% % NC_VARPUT(NCFILE,VARNAME,DATA,START,COUNT) writes DATA contiguously,
% % starting at the zero-based index START and with extents given by
% % COUNT.
% %
% % NC_VARPUT(NCFILE,VARNAME,DATA,START,COUNT,STRIDE) writes DATA
% % starting at the zero-based index START with extents given by
% % COUNT, but this time with strides given by STRIDE.  If STRIDE is not
% % given, then it is assumes that all data is contiguous.
%
%
% bak jc191 6 Feb 2020
%

args = varargin(:);
start = [];
count = [];
stride = [];
switch length(args)
    case 1
        start = args{1};
    case 2
        start = args{1};
        count = args{2};
    case 3
        start = args{1};
        count = args{2};
        stride = args{3};
    otherwise
end

ncid = netcdf.open(ncfile,'WRITE');

varid = netcdf.inqVarID(ncid,varname);

% If there is start but no count, then calculate count to retrieve from
% start to the end of each dimension

[varname,xtype,dimids,natts] = netcdf.inqVar(ncid, varid);

if isempty(count) & ~isempty(start)
    
    % calculate the size of count to ensure writing from start to the end
    % of each dimension
    
    % we seem to need to flip the dimids to get the same effect as the snctools
    % nc_varput
    
    dimids = fliplr(dimids);
    
    ndimsv = length(dimids);
    clear dimsize
    for kd = 1:ndimsv
        [dimname, dimlength] = netcdf.inqDim(ncid, dimids(kd));
        dimsize(kd) = dimlength;
    end
    
    count = dimsize(:)'-start;
    
end

% I couldn't see anywhere where mexec calls nc_varget with start but no
% count, so the above difference should not matter.

start = fliplr(start);
count = fliplr(count);
stride = fliplr(stride);


% now handle _FillValue

switch ( xtype )
    case { 6 } % 6 is double
        fillvalue = netcdf.getAtt(ncid, varid, '_FillValue');
        vardata(isnan(vardata)) = fillvalue;
    otherwise
        
end

% Now transpose; mexec files are always 2-D

if length(dimids) == 2
    vardata = vardata'; % this is necessary to mimic the action of the old nc_varget;
    %     the above line will only work on 2-D vars, ie 1xN, Mx1, MxN.
    %     mexec is not presently set up to handle more than 2-D vars.
    %     mexec files have at least three dimension parameters: n_unity, nrows1, ncols1.
    %     mexec variables are always 2-D. MxN 1xN or Mx1.
end

if isempty(start)
    netcdf.putVar(ncid, varid, vardata );
elseif isempty(count)
    fprintf(2,'\n%s\n','Warning, nc_varget has been called with start but no count');
    fprintf(2,'%s\n','The bahaviour of this version is different than the behaviour of the snctools version');
    fprintf(2,'%s\n\n','Suggest the code be rewritten to state exactly what ''count'' should be');
    error('error in nc_varget');
    % I don't know what happens in putvar if there is start but not count
    % getvar reads only one point.
    netcdf.putVar(ncid, varid, start, vardata );
elseif isempty(stride) % assume it is 1
    %     k1 = start(1)+ (1:count(1));
    %     k2 = start(2)+ (1:count(2));
    netcdf.putVar(ncid, varid, start, count, vardata );
else
    %     k1 = start(1)+1+stride(1)*(0:count(1)-1);
    %     k2 = start(2)+1+stride(2)*(0:count(2)-1);
    netcdf.putVar(ncid, varid, start, count, stride, vardata);
end


netcdf.close(ncid);

return