function [gdat_data,gdat_params,error_status,varargout] = gdat(shot,data_request,varargin)
%
% function [gdat_data,gdat_params,error_status,varargout] = gdat(shot,data_request,varargin)
%
% Aim: get data from a given machine using full path or keywords. 
%      Keywords should be the same for different machines, otherwise add "_machinname" to the keyword if specific
%      Keywords are and should be case independent (transformed in lower case in the function and outputs)
%
% If no inputs are provided, return the list of available keywords in gdat_data and default parameters gdat_params
%
% Inputs:
%
%    no inputs: return default parameters in a structure form in gdat_params
%    shot: shot number
%    data_request: keyword (like 'ip') or trace name or structure containing all parameters but shot number
%    varargin{i},varargin{i+1},i=1:nargin-2: additional optional parameters given in pairs: param_name, param_value
%                                            The optional parameters list might depend on the data_request
%              examples of optional parameters:
%                               'plot',1 (plot is set by default to 0)
%                               'machine','TCV' (the default machine is the local machine)
%
%
% Outputs:
%
% gdat_data: structure containing the data, the time trace if known and other useful information
% gdat_data.t : time trace
% gdat_data.data: requested data values
% gdat_data.dim : values of the various coordinates related to the dimensions of .data(:,:,...)
%                     note that one of the dim is the time, replicated in .t for clarity
% gdat_data.dimunits : units of the various dimensions, 'dimensionless' if dimensionless
% gdat_data.error_bar : if provided
% gdat_data.gdat_call : list of parameters provided in the gdat call (so can be reproduced)
% gdat_data.shot: shot number
% gdat_data.machine: machine providing the data
% gdat_data.gdat_request: keyword for gdat if relevant
% gdat_data.data_fullpath: full path to the data node if known and relevant, or expression, or relevant function called if relevant
% gdat_data.gdat_params: copy gdat_params for completeness
% gdat_data.xxx: any other relevant information
%
% gdat_params contains the options relevant for the called data_request. It also contains a help structure for each option
% eg.: param1 in gdat_params.param1 and help in gdat_params.help.param1
%
% Examples:
% (should add working examples for various machines (provides working shot numbers for each machine...))
% 
%    [a1,a2]=gdat;
%    a2.data_request = 'Ip';
%    a3=gdat(48836,a2);  % gives input parameters as a structure, allows to call the same for many shots
%    a4=gdat('opt1',123,'opt2',[1 2 3],'shot',48832,'data_request','Ip','opt3','aAdB'); % all in pairs
%    a5=gdat(48836,'ip'); % standard call
%    a6=gdat(48836,'ip','Opt1',123,'Doplot',1,'opt2','Abc'); % standard call with a few options (all lowercase in output)


%
% Comments for local developer:
% This gdat is just a "header routine" calling the gdat for the specific machine gdat_`machine`.m which can be called
% directly, thus which should be able to treat the same type of input arguments
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Prepare some variables, etc

% for backward compatibility (with most recent simple call ala: gdat(shot,'data_request',doplot,machine) )
% if nargin<=4 and >2 and 1st and 3rd are numeric, assume this is an old call and transform it to:
% gdat(shot,'data_request','doplot',doplot','machine',machine)
% and a warning
if nargin>2
  varargin_eff = varargin;
  if nargin>=3 && nargin<=4  && isnumeric(shot) && isnumeric(varargin{1})
    % assume old call: gdat(shot,'data_request',doplot[,machine])
    varargin_eff{1} = 'doplot';
    varargin_eff{2} = varargin{1};
    if nargin==4
      varargin_eff{3} = 'machine';
      varargin_eff{4} = varargin{2};
    end
  end
end

fusion_machine_defaultname=getenv('FUSION_MACHINE_DEFAULTNAME');
default_machine = 'tcv';
if ~isempty(fusion_machine_defaultname)
  default_machine = lower(fusion_machine_defaultname);
else
  [s,hostname]=unix('hostname -a');
  if s || isempty(hostname), hostname=getenv('HOSTNAME');end
  if ~isempty(regexpi(hostname,'epfl'))
    default_machine = 'tcv';
  elseif ~isempty(regexpi(hostname,'rzg.mpg'))
    default_machine = 'aug';
  end
end
machine_eff = default_machine;

% do not treat inputs here but in subsequent gdat_machine.m function, however, need to extract machine name if provided:
if nargin>=2 % need at least 2 inputs to have 'machine','aug' as arguments (to ask specific list of requests)
  % in case start directly with pairs of options
  if ischar(shot) && strcmp(lower(shot),'machine') && ischar(data_request)
    machine_eff = data_request;
  elseif isstruct(shot) && isfield(shot,'machine')
    machine_eff = shot.machine;
  elseif isstruct(data_request) && isfield(data_request,'machine')
    machine_eff = data_request.machine;
  elseif nargin>=3
    imachine=[];
    for i=1:length(varargin_eff)
      if ischar(varargin_eff{i})
        ii = strmatch(varargin_eff{i},'machine','exact');
        if ~isempty(ii); imachine = i; end
      end
    end
    if ~isempty(imachine) && length(varargin_eff)>=imachine+1 && ~isempty(varargin_eff{imachine+1})
      machine_eff = varargin_eff{imachine+1};
    end
  end
end

% add paths to each machine which are in subdirectory of gdat and working
% add only given machine directory using machine_eff...
gdat_path = mfilename('fullpath');
eval(['addpath ' gdat_path(1:end-4) upper(machine_eff)]);
    
% copy gdat present call:
gdat_call = [];
if nargin==0
  subcall=['gdat;'];
elseif nargin>=1
  if isnumeric(shot)
    subcall=['gdat(' num2str(shot) ];
  elseif ischar(shot)
    subcall=['gdat(' shot ];
  else
    warning('type of 1st argument unexpected, should be numeric or char')
    gdat_call = [];
    return
  end
  if nargin>=2
    if isempty(data_request)
      subcall = [subcall ',[]'];
    else
      substring = subcall_all2str(data_request);
      subcall = [subcall substring];
    end
    if nargin>=3
      substring = subcall_all2str(varargin_eff{:});
      subcall = [subcall substring];
    end
  end
  % ... to continue
  subcall = [subcall ');'];
end

gdat_call = [subcall ' % nargout = ' num2str(nargout)];

% Note: would need to check nargout to make call consistent, but to avoid this, each gdat_xxx should return at least an empty varargout: varargout{1}=cell(1);
% copy subcall here so is last subnode
try
  if nargin==0
    eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) ';']);
  elseif nargin==1
    eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot);']);
  elseif nargin==2  
    eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot,data_request);']);
  else
    eval(['[gdat_data,gdat_params,error_status,varargout] = gdat_' lower(machine_eff) '(shot,data_request,varargin_eff{:});']);
  end
catch ME_gdat
  warning(['problems calling gdat_' lower(machine_eff)]);
  if ~exist('gdat_data'); gdat_data.data = []; end
  if  ~isfield(gdat_data,'dim'); gdat_data.dim=[]; end
  if ~exist('gdat_params'); gdat_params.plot = []; end
  if ~exist('error_status'); error_status = 998; end
  if exist('ME_gdat')
    getReport(ME_gdat)
  end
  return
end
  
gdat_data.gdat_call = gdat_call;

if gdat_data.gdat_params.doplot
  try
    % plot gdat_data versus 1st dim by default, if nb_dims<=2, otherwise do not plot
    hhh = gdat_plot(gdat_data); % return handle to figure
  catch ME_gdat_plot
    hhh = [];
  end
  if nargout >=3
    if length(varargout)==0 || isempty(varargout{1})
    varargout{1} = hhh;
    else
    varargout{end+1} = hhh;
    end
  end
end

if exist('ME_gdat_plot')
  getReport(ME_gdat_plot)
end
