function [argout1, argout2, argout3, argout4, argout5, argout6] = getdino(...
    mode, get_ranges, get_dset, get_vars, get_dset_stride, ...
    get_num_urls, get_georange, get_variables, get_archive, ...
    whichurl)
%
% these are used only locally
%
global Pass_Times old_var old_dset old_ranges Pass_Depths
%
% explanation:  This function is used to access any number of
% gridded datasets.
%
% get_ranges = [WestLon EastLon   -- units: decimal degrees
%           SouthLat NorthLat -- units: decimal degrees
%           MinDepth MaxDepth -- units: meters
%           MinTime  MaxTime]  -- units: decimal years
%
% Mode may be 'cat' (Catalogue data holdings), 'datasize' (estimate
% size of data request, or 'get' (Get Data).

% The preceding empty line is important.
%
% $Id: getrectg.m,v 1.21 1998/11/05 16:01:52 root Exp $

% $Log: getrectg.m,v $
% Revision 1.21  1998/11/05 16:01:52  root
% Changed LonVector and LatVector to be used if no Lon returned and tried the update function.
% DataScale and DataNull should now be optional!
%
% Revision 1.20  1998/11/05 13:07:10  root
% *** empty log message ***
%
% Revision 1.2  1998/09/14 01:32:54  dbyrne
% Elminated an inconsistency whereby the depth variable was not scaled
% and had no DataNull etc.  Added check for empty variables to plotscript.m
%
% Revision 1.17  1998/09/13 19:59:31  root
% *** empty log message ***
%
% Revision 1.16  1998/09/13 19:21:23  root
% Eliminated an inconsistency in DataScale, DataRange, and DataNull, that
% Depth was not included!
%
% Revision 1.15  1998/09/12 16:56:29  root
% Fixed bug in catalogue determination in datasize mode.
%
% Revision 1.14  1998/09/12 10:43:15  root
% *** empty log message ***
%
% Revision 1.13  1998/09/12 10:32:24  root
% Filled in blank time names with Pass_Times
%
% Revision 1.12  1998/09/12 09:59:29  root
% Changed Time to TimeRange.
%
% Revision 1.11  1998/09/11 08:32:14  dbyrne
% *** empty log message ***
%
% Revision 1.10  1998/09/10 21:11:48  dbyrne
% Removed informative blurbs returned to user from getrectg and added
% them to browser.
%
% Revision 1.9  1998/09/10 09:34:12  dbyrne
% Changed datasize estimate to take into account multiple variables.
%
% Revision 1.8  1998/09/10 08:56:24  dbyrne
% Changed input to getfunctions so mode is first arg.
%
% Revision 1.7  1998/09/09 19:42:10  dbyrne
% *** empty log message ***
%
% Revision 1.6  1998/09/09 15:04:27  dbyrne
% Eliminating all global variables.
%
% Revision 1.5  1998/09/09 09:23:12  dbyrne
% Changes to make creation of a 'time' variable more sensible.
%
% Revision 1.4  1998/09/09 07:57:36  dbyrne
% replaced Data_Scale with DataScale, Data_Null with DataNull, and Data_Range
% with DataRange for consistency with other variables in the archive.m files.
%
% Revision 1.3  1998/09/08 20:35:39  dbyrne
% fixed bug with variablelist
%
% Revision 1.2  1998/09/08 14:59:06  dbyrne
% Modifications for multiple servers ....
%
% Revision 1.1  1998/09/08 11:09:06  dbyrne
% This function replaces 'getrectangular'.
%
% Revision 1.6  1998/09/03 17:12:21  dbyrne
% added index into returned variables as return argument.
% This is so that DataScale can be used correctly in plotscript
%
% Revision 1.5  1998/09/03 17:01:01  dbyrne
% more changes for multivariables
%
% Revision 1.4  1998/09/01 11:44:50  dbyrne
% making changes for multivariables
%
% Revision 1.3  1998/09/01 07:15:07  dbyrne
% fixed problem with computation of num_urls
%
% Revision 1.2  1998/09/01 06:52:24  dbyrne
% working on multivariate changes
%
% Revision 1.1  1998/08/27 16:37:16  dbyrne
% developing changes for multivars -- DAB
%
% Revision 1.1  1998/05/17 14:18:04  dbyrne
% *** empty log message ***
%
% Revision 1.12  1998/02/19 20:01:25  jimg
% DataNull is now a vector.
%
% Revision 1.11  1998/01/14 17:17:00  jimg
% Added DataNull variable in scaling code.
%
% Revision 1.10  1997/12/09 16:31:16  jimg
% Changed user_services@ to support@.
%
% Revision 1.9  1997/12/09 06:42:16  jimg
% Merged my code and Deirdre's. Now fails all the time for me. Arrgh...
%
% Revision 1.8  1997/12/09 01:22:16  dbyrne
% Removed faulty documentation.
%
% Revision 1.7  1997/12/04 23:38:20  jimg
% Changed deblank(DodsName...) to dods_dbk(DodsName...). this new version of
% deblank does all that deblank does plus folds http escape sequences (%<d><d>)
% to underscores.
%
% Revision 1.5  1997/11/12 18:36:53  tom
% modified to deal with null values. Not ideal, but better.
%
% Revision 1.4  1997/10/25 18:02:03  jimg
% Added to GUI
%
% Revision 1.3  1997/10/10 02:32:24  tom
% Revoked last correction. Cure worse than disease.
%
% Revision 1.2  1997/10/10 01:53:27  tom
% Slightly fixed error checking for bad URL.
%
% Revision 1.1.1.1  1997/09/22 14:13:54  tom
% Imported Matlab GUI sources to CVS
%
if exist(get_archive) == 2
  eval(get_archive)
  % fill empty time string 
  if isempty(TimeName)
    TimeName = 'browse_time';
  end
else
  disp(['Problem reading dataset metadata ' get_archive '.m'])
  return
end

if nargin >= 1
  % initialize return arguments
  argout1 = [];
  argout2 = [];
  argout3 = [];
  argout4 = [];
  argout5 = [];
  argout6 = [];
  
  if strcmp(mode,'cat')
    % save these values
    old_ranges = get_ranges;
    old_dset = get_dset;
    old_var = get_vars;
    %
    %  Need to get the vector of times with values for middle of each day that is
    %  within the range of start and end days. This portion of the program
    %  assumes that there is one field per day exactly in the middle of the day.
    %
    
    % Before call, make sure that the range requested overlaps with the data range.
    
    if (get_ranges(4,1) > TimeRange(2)) | (get_ranges(4,2) < TimeRange(1)) ...
        | (get_ranges(3,1) > DepthRange(2)) | (get_ranges(3,2) < DepthRange(1))
      disp('Requested range does not overlap data. Respecify')
      return
    end
    
    if strcmp( CatalogServer, 'daily')
      if exist('RefTime') == 0
	RefTime = NaN;
      end
      [times, Pass_Times] = daily(TimeRange, [IntervalTime MidTime ...
	    RefTime], get_ranges);
      if strcmp(get_archive,'reyweek') % should this be implemented for all?
	t = thisday;
	i = find(times < t);
	times = times(i);
	Pass_Times = Pass_Times(i,:);
      end
    elseif strcmp(CatalogServer, 'monthly')
      [times, Pass_Times] = monthly(TimeRange, get_ranges);
    else
      % adds depth and scaling functionality   K.L. 11/98
      eval(['[times, Pass_Times, depths, Pass_Depths, url] = ', Cat_m_File, ...
	    '(CatalogServer, get_archive, TimeRange, DepthRange, get_ranges);'])
      argout6 = url;
    end
    % catch rude catalogue servers that do not return args if empty!
    % D. B. 98/04/13
    if exist('times') ~= 1
      times = [];
    end
    if exist('Pass_Times') ~= 1
      times = [];
    end
    if exist('depths') ~= 1
      depths = [];
    end
    if exist('Pass_Depths') ~= 1
      depths = [];
    end
    % one argument for each range (x,y,z,t) accepted by browser
    argout3 = depths;
    argout4 = times;
    % this is a kludge to determine the number of URLs required ...
    if any(length(argout1) > 0 | length(argout2) > 0 | ...
      length(argout3) > 0 | length(argout4) > 0)
      argout5 = max(length(argout1),1) * max(length(argout2),1) * ...
	  max(length(argout3),1) * max(length(argout4),1);
    else
      argout5 = 0;
    end
    return
    
  elseif strcmp(mode,'datasize')
    
    %  see if dataset request has changed at all get inventory again.

    if isempty(old_var) | isempty(old_dset) | isempty(old_ranges)
      [x,y,z,t,n,URL] = getdino('cat', get_ranges, get_dset, get_vars, ...
	  get_dset_stride, get_num_urls, get_georange, get_variables, ...
	  get_archive);
      get_num_urls = n;
    end
    
    if size(get_vars) ~= size(old_var) | (get_dset ~= old_dset) | ...
	  any(any(get_ranges ~= old_ranges))
      [x,y,z,t,n,URL] = getdino('cat',get_ranges, get_dset, get_vars, ...
	  get_dset_stride, get_num_urls, get_georange, get_variables, ...
	  get_archive);
      get_num_urls = n;
    end
    
    if get_num_urls > 0
      %  The browser always sets the longitude range to go from -180 to 180.  Need
      %  to find out how the data set specifies the longitude range: -180 to 180 or
      %  0 to 360 and set up start and end longitudes accordingly. If the range
      %  selected in the browser is between 0 and 180 it does not matter.
      LL = LonRange(1);
      RL = LonRange(2);
      LonDirection = 1;
      if LL > RL % Data goes from east to west in the data set. Swap LL and RL.
	temp = LonRange(1);
	LL = LonRange(2);
	RL = temp;
	LonDirection = -1;
      end
      startLon = get_ranges(1,1);
      endLon = get_ranges(1,2);
      if endLon < startLon 
	startLon = startLon - 360.0;
      end
      % Make sure that the west end of the range is to the 
      % east of the west end of the data set.
      if startLon < LL
	temp = (1 + floor((LL - startLon) / 360.0)) * 360;
	startLon = startLon + temp;
	endLon = endLon + temp;
      end
      if abs(get_ranges(1,1) - get_ranges(1,2)) >= 360
	if LL < RL
	  startLon = LL;
	  endLon = RL;
	else
	  startLon = RL;
	  endLon = LL;
	end
      else % this is still incorrect if the constraints match up! dab 98/04/14
	% Now examine the east end of the data set.
	if startLon < RL
	  if endLon <= RL
	  else
	    if (endLon-360) > LL
	      %   Set up to make A SECOND CALL for the same URL
	      endLon(2) = endLon - 360;
	      endLon(1) = RL;
	      startLon(2) = LL;
	    else
	      endLon = RL;
	    end
	  end
        else
	  startLon = startLon - 360;
	  endLon = endLon - 360;
	  if endLon <= LL
	    disp('Longitude range does not overlap the data set. ')
	    return
	  else
	    startLon = LL;
	    % East end of range east of west end of data set, 
	    %now check it against east end.
	    if endLon > RL
	      endLon = RL;
	    end	      
	  end
	end
      end
      %  end % of /* if abs(ranges(1,1) - ranges(1,2)) >= 360 */
    end
    if ~all(size(startLon) == size(endLon))
      disp('problem with longitude transformation')
    else
      for i = 1:length(startLon)
	sLon = startLon(i);
	eLon = endLon(i);
	% run a script to transform longitude to pixel number
	%pixcheck
	if get_num_urls > 0
	  % accumulate volumes if two calculations were necessary
	  if isempty(argout1)
            % Since pixcheck is not used, use whole data range to approximate it.  K.L. 11/98
	    %argout1 = length(StartRow:get_dset_stride:EndRow) * ...
	    %	length(StartColumn:get_dset_stride:EndColumn) * ...
	    %	length(get_vars) * 8 / 1e6;
            argout1 = length(get_vars) * Nlat * Nlon * 8 / 1e6;
	  else
	    %argout1 = argout1 + ...
	    %	length(StartRow:get_dset_stride:EndRow) * ...
	    %	length(StartColumn:get_dset_stride:EndColumn) * ...
	    %	length(get_vars) * 8 / 1e6;
            argout1 = argout1 + length(get_vars) * Nlat * Nlon * 8 / 1e6;
	  end
	  argout2 = get_num_urls;
	  if get_num_urls > 1
	    argout1 = argout1 * get_num_urls;
	  end
	end
      end
    end
    return
    
  elseif strcmp(mode,'get')
    
    if get_num_urls > 0 % we have a catalogue -- we can just issue the request
      %  The browser always sets the longitude range to go from -180 to 180.  Need
      %  to find out how the data set specifies the longitude range: -180 to 180 or
      %  0 to 360 and set up start and end longitudes accordingly. If the range
      %  selected in the browser is between 0 and 180 it does not matter.
      LL = LonRange(1);
      RL = LonRange(2);
      LonDirection = 1;
      if LL > RL % Data goes from east to west in the data set. Swap LL and RL.
	temp = LonRange(1);
	LL = LonRange(2);
	RL = temp;
	LonDirection = -1;
      end
      startLon = get_ranges(1,1);
      endLon = get_ranges(1,2);
      if endLon < startLon 
	startLon = startLon - 360.0;
      end
      % Make sure that the west end of the range is to the 
      % east of the west end of the data set.
      if startLon < LL
	temp = (1 + floor((LL - startLon) / 360.0)) * 360;
	startLon = startLon + temp;
	endLon = endLon + temp;
      end
      if abs(get_ranges(1,1) - get_ranges(1,2)) >= 360
	if LL < RL
	  startLon = LL;
	  endLon = RL;
	else
	  startLon = RL;
	  endLon = LL;
	end
      else % this is still incorrect if the constraints match up! dab 98/04/14
	% Now examine the east end of the data set.
	if startLon < RL
	  if endLon <= RL
          else
	    if (endLon-360) > LL
	      %   Set up to make A SECOND CALL for the same URL
	      endLon(2) = endLon - 360;
	      endLon(1) = RL;
	      startLon(2) = LL;
	    else
	      endLon = RL;
	    end
	  end
	else
	  startLon = startLon - 360;
	  endLon = endLon - 360;
	  if endLon <= LL
	    disp(['Longitude range does not overlap the data set. ', ...
	      'No data request posted.'])
	    return
	  else
	    startLon = LL;
	    % East end of range east of west end of data set, 
	    %now check it against east end.
	    if endLon > RL
	      endLon = RL;
	    end	      
	  end
	end
      end
      %  end % of /* if abs(ranges(1,1) - ranges(1,2)) >= 360 */
    end

    if ~all(size(startLon) == size(endLon))
      disp('problem with longitude transformation')
    else

      % construct lists from which to make URLs
      whichvariables = [];
      for i = 1:size(get_variables,1)
	for j = 1:size(SelectableVariables,1)
	  if strcmp(deblank(get_variables(i,:)), deblank(SelectableVariables(j,:)))
	    whichvariables = [whichvariables j];
	  end
	end
      end
      if ~isempty(whichvariables)
	variablelist = DodsName(whichvariables,:); 
	% take into account that there may be mutliple servers
	if size(Server,1) > 1
	  serverlist = Server(whichvariables,:); 
	else
	  serverlist = Server; 
	end
      else
	disp('Getrectg: No variables were selected!')
      end
      VERSION = version; VERSION = str2num(VERSION(1));
      % make up a time and depth variable to pass back for those datasets
      % that do not have a time/depth variable.
      if whichurl >= 1
        % adds up for multiple time and depth selections  K.L. 11/98
        if (exist('Pass_Times') == 1) & (exist('Pass_Depths') == 1)
          timesize = size(Pass_Times,1);
          depthsize = size(Pass_Depths,1);
          timewhichurl = ceil(whichurl/depthsize);
          depthwhichurl = whichurl - (timewhichurl-1)*depthsize;
        else
          timewhichurl = whichurl;
          depthwhichurl = whichurl;
        end
      end
      if exist('Pass_Times') == 1
	browse_time = Pass_Times(timewhichurl,:);
      end
      if exist('Pass_Depths') == 1
        browse_depth = Pass_Depths(depthwhichurl,:);
      end
      % loop through as many longitude spans as necessary
      % I don't think the for loop is needed for this dataset, but keep it anyway. K.L. 11/98
      for k = 1:length(startLon)
	sLon = startLon(k);
	eLon = endLon(k);
        %We don't need pixcheck here. Grid points are defined in URL function.
	%pixcheck
	if size(DodsName,1) ~= size(SelectableVariables,1)
	  disp([ 'There is a problem in the archive.m file: ', ...
		'the number of DodsNames and SelectableVariables does not', ...
		'match']) 
	  return
	end
	
	% construct and evaluate URL(s)
        if size(serverlist,1) == 1
	  % there will be only one URL.  Initialize it.
	  iURL = '';
	  % return the URL to be displayed by the browser. D.B. 98/4/5
	  eval([ 'iURL =  ', URL_m_File, '(get_archive, Pass_Times(timewhichurl,:),', ...
                'Pass_Depths(depthwhichurl,:),', ...
		'get_dset_stride, get_ranges, variablelist, serverlist);'])
	  if ~isempty(iURL)
	    argout5 = iURL;
	    % because of v4 name length bug and the fact we have no info
	    % about the ORDER of returning variables, we might have to 
	    % evaluate some more URLs here:
	    loaddods(iURL);
	    if VERSION < 5
	      for i = 1:size(variablelist,1)
		s(i) = size(dods_dbk(variablelist(i,:)),2);
	      end
	      if any(s > 19)
		i = find(s > 19);
		% split the URL into several, one for each
		% variable whose name is too long
		for j = 1:length(i)
		  eval([ 'jURL =  ', URL_m_File, '(get_archive, ', ...
			'Pass_Times(timewhichurl,:), Pass_Depths(depthwhichurl,:),',  ...
			'get_dset_stride, get_ranges,variablelist(i(j)),serverlist);'])
		  tmpname = dods_dbk(variablelist(i(j),:));
		  tmpname = tmpname(1:19);
		  eval([ '[' tmpname '] = loaddods(jURL);' ]);
		end
	      end
	    end % end of version 4 name-bug check
	  end
	else
	  % there is > 1 server and there will be multiple URLs
	  iURL = ''; argout5 = '';
	  % return the URL to be displayed by the browser. D.B. 98/4/5
	  for l = 1:size(serverlist,1)
	    eval([ 'iURL =  ', URL_m_File, '(get_archive, Pass_Times(timewhichurl,:),', ...
                  'Pass_Depths(depthwhichurl,:),', ...
		  'get_dset_stride,', ...
		  'get_ranges, variablelist(l,:), serverlist(l,:));'])
	    if ~isempty(iURL)
	      argout5 = [iURL ' ' argout5];
	      % because of v4 name length bug and the fact we have no info
	      % about the ORDER of returning variables, we might have to 
	      % evaluate some more URLs here:
	      if VERSION < 5
		s = size(dods_dbk(variablelist(l,:)),2);
		if s <= 19  
		  loaddods(iURL);
		else
		  loaddods(iURL);
		  eval([ '[' tmpname '] = loaddods(iURL);' ]);
		end
	      else
		loaddods(iURL);
	      end
	    end
          end % end of loop through different servers
        end
	
	% convert longitude to browser coordinates
	if ~isempty(dods_dbk(LongitudeName))
	  if exist(dods_dbk(LongitudeName)) == 1
	    TempLongitude = eval(LongitudeName);
	    if abs(get_ranges(1,1) - get_ranges(1,2)) >= 360
	      % the data were not split into 2 fetch args!
	      % don't fiddle with them
	    else
	      if get_georange(1) == -180
		TempLongitude = (TempLongitude >=180).*(TempLongitude-360)+ ...
		    (TempLongitude < -180).*(TempLongitude+360)+ ...
		    (TempLongitude >= -180 & TempLongitude < 180).*TempLongitude;
	      elseif get_georange(1) == 0
		TempLongitude = (TempLongitude >= 360).*(TempLongitude-360)+ ...
		    (TempLongitude < 0).*(TempLongitude+360)+ ...
		    (TempLongitude >= 0 & TempLongitude < 360).*TempLongitude;
	      end
	    end
	    eval([LongitudeName '= TempLongitude; clear TempLongitude'])
	  end
	end
	% now make up a list of all returned variables
	% (above list plus time, longitude, latitude, depth),
	% evaluate their sizes, scale them and convert nulls to NaNs.
	% this has to be a temporary variable list -- 'variablelist'
	% is still in use
	if isempty(LongitudeName)
	  LongitudeName = 'LonVector';
	end
	if isempty(LatitudeName)
	  LatitudeName = 'LatVector';
	end
	tmpvariablelist = str2mat(TimeName,LongitudeName,LatitudeName, ...
	    DepthName, variablelist);
	tmpwhichvariables = [1 2 3 4 whichvariables+4];
	for i = 1:size(tmpvariablelist,1)
	  tmpname = dods_dbk(tmpvariablelist(i,:));
	  if VERSION < 5 % fix v4 bug
	    if size(tmpname,2) > 19
	      tmpname = tmpname(1:19);
	    end
	  end
          %if ~isempty(deblank(tmpname))
	    if exist(tmpname) == 1
	      % make a temporary variable to work with
	      tmpout = eval(tmpname);
	      sizes(i,:) = size(tmpout);
	      if exist('DataNull') == 1
		if ~isnan(DataNull(tmpwhichvariables(i)))
		  j = find(tmpout == DataNull(tmpwhichvariables(i)));
		  tmpout(j) = NaN*j;
		else
		  % do nothing because null values are already NaNs
		end
	      else
		% if we have no defined null, do nothing
		% we used to do this!: (bad, bad)
		% j = find(tmpout < -1.0e+33);
		% tmpout(j) = NaN*j;
	      end
	      % stack data in a column and scale it if possible
	      if exist('DataScale') == 1
		if size(DataScale,1) ~= size(SelectableVariables,1)+4
		  disp('Data cannot be auto-scaled.')
		  disp(['Error is in ' get_archive '.m'])
		  argout1 = [argout1; tmpout(:)];
		else
		  if ~isnan(DataScale(tmpwhichvariables(i),1))
		    argout1 = [argout1; DataScale(tmpwhichvariables(i),1) + ...
			  tmpout(:)*DataScale(tmpwhichvariables(i),2)];
		  else % scale exists but is a nan -- don't scale
		    argout1 = [argout1; tmpout(:)];
		  end
		end
	      else % there is no DataScale
		argout1 = [argout1; tmpout(:)];
	      end
	    else % the supposedly returned variable DOES NOT EXIST 
	      % in this workspace.  Put in an empty placeholder.
	      if ~isempty(tmpname)
		eval([tmpname '= [];'])
	      end
	      sizes(i,:) = [0 0];
	    end
	  %end
        end
	% now convert variablelist to user-friendly names
	names = str2mat('Time','Longitude','Latitude', 'Depth', ...
	    SelectableVariables(whichvariables,:));
	% ------------------------ start producing output arguments
	if length(startLon) > 1
	  % we have to unpack the variables
	  total_size = 0;
	  for j = 1:size(sizes,1);
	    string = sprintf('tmp%i%4.4i = %s;',k, j, ...
		[ 'reshape(argout1((1:sizes(j,1)*sizes(j,2))+',...
		  'total_size),sizes(j,1),sizes(j,2))']);
	    eval(string)
	    total_size = sizes(j,1)*sizes(j,2)+total_size;
	  end
	  argout1 = [];
	  if k == 1
	    URL = argout5;
	  else
	    URL = [URL ' ' argout5];
	    for j = 1:size(sizes,1)
	      % if it's not Time or Latitude, 'combine' it
	      if ~strcmp(deblank(names(j,:)),'Time') & ...
		    ~strcmp(deblank(names(j,:)),'Latitude')
		eval(sprintf('tmp%i%4.4i=combine(tmp%i%4.4i,tmp%i%4.4i);', ...
		    k, j, k-1, j, k, j))
	      end
	      eval(sprintf('sizes(j,:) = size(tmp%i%4.4i);',k, j))
	      eval(sprintf('argout1 = [argout1; tmp%i%4.4i(:)];',k,j))
	    end % end of loop through j = num_args 
	  end
	else
	  URL = argout5;
	end % end of if length(startLon) > 1
      end % end of 'for' loop through length of startLon
      argout2 = sizes;
      argout3 = names;
      argout4 = tmpwhichvariables;
      argout5 = URL;
    end
    return
  end % strcmp(mode) 
end % if nargin >= 1
