//  CDFDataBaseDataSource.h
//
//  Qdos - data interfacing
//
//  David Burgess
//  March 2000
//

#ifndef Q_CDFDATABASEDATASOURCE_H
#define Q_CDFDATABASEDATASOURCE_H

#include <map>
#include "Exception.h"
#include "Viostream.h"
#include "DataSource.h"
#include "CDFDataConfigurationMap.h"
#include "QdTime.h"
#define DATA "data"
#define METADATA "metadata" 


namespace QDOS {

class CDFDataBaseException :public Exception {
public:
  CDFDataBaseException( ExceptionMsg m="" )
   : Exception(m<<" [CDFDataBaseException]" ) {;}
};

class CDFDataBaseDataSource;

Vostream& operator<<(Vostream& v_os,const CDFDataBaseDataSource& cdf_db);
Vistream& operator>>(Vistream& v_is, CDFDataBaseDataSource& cdf_db);

class CDFDataBaseDataSource : public DataSource, TimeStructuredDataSource 
{

  friend Vostream& operator<<(Vostream&,const CDFDataBaseDataSource&);
  friend Vistream& operator>>(Vistream&, CDFDataBaseDataSource&);

  class DataIntervalInfo {
    bool data_type_ok;
    long cdf_data_type;
    vector<int> data_dims;
    
    bool time_smi_ok;
    int time_smi_rec_start;
    int time_smi_num_rec;
    Time time_smi_time_interval; // actual time to be used
    
    friend class CDFDataBaseDataSource;
  
  public:
    DataIntervalInfo(void)
      : data_type_ok(false), time_smi_ok(false) {;}
    DataIntervalInfo( const DataIntervalInfo& a )
      : data_type_ok(a.data_type_ok),
        cdf_data_type(a.cdf_data_type),
        data_dims(a.data_dims),
        time_smi_ok(a.time_smi_ok),
        time_smi_rec_start(a.time_smi_rec_start),
        time_smi_num_rec(a.time_smi_num_rec),
        time_smi_time_interval(a.time_smi_time_interval) {;}
  };

  CDFDataConfigurationMap_var cdf_data_configmap;
  DataNamesTable_var data_names;
  map<string,IgnoreNumericDataFunctor_var> numeric_ignoration_table;
  string _dcm_file_name;
  CDFDCMReadStatus _dcm_read_status;

  void check_data_type( 
       const CDF_DCMDataIntervalList& data_intervals,
       vector<DataIntervalInfo>& info );

public:
  CDFDataBaseDataSource():_dcm_read_status(CDFDCM_SUCCESS){;}
  CDFDataBaseDataSource( const string& data_config_file_name )
  { open( data_config_file_name ); }

  ~CDFDataBaseDataSource(){close();}
  
  void open(const string& dcm_file_name)
  {
    _dcm_read_status=CDFDCM_SUCCESS;	  
    if(!cdf_data_configmap.is_nil())
      close();
    _dcm_file_name=dcm_file_name;
    try{
      cdf_data_configmap=new CDFDataConfigurationMap;
      _dcm_read_status=cdf_data_configmap->read_file(dcm_file_name);
    }
    catch(Exception& e)
    {_dcm_read_status=CDFDCM_FAILURE;}
  }

  void close();

  CDFDCMReadStatus get_dcm_read_status() const
  {return _dcm_read_status;}
  
  DataNamesTable_var get_data_names(void);
  DataNamesTable_var get_meta_names(const string& data_name="");
  DataNamesTable_var get_names(void);
  
  void get_meta_names(const string& data_name, vector<string>& mnames)
  { 
      DataNamesTable_var meta_names_table=get_meta_names(data_name);
      if(!meta_names_table.is_nil())
        meta_names_table->list_names_r(mnames);
  }

  void get_database_name(string& dcm_file_name)
  {  dcm_file_name=_dcm_file_name;}
  void get_dcm_filenames(vector<string>& fnames)
  { cdf_data_configmap->get_dcm_filenames(fnames);}
  
  DataNamesTable_var get_datafile_names()
  {return cdf_data_configmap->get_file_names();}

  DataNamesTable_var get_datafile_names(const string& data_name, 
    const TimeInterval& tint) 
  {return cdf_data_configmap->get_file_names(data_name,tint);}
  
  void get_data_info(const string& data_name, vector<string>& info,\
    const TimeInterval& tint=TimeInterval())
  { 
    TimeInterval ltint(tint);
    if(ltint.empty())
      cdf_data_configmap->get_time_range(data_name,ltint);
    cdf_data_configmap->get_data_info(data_name,info,tint); 
  }
 
  int get_num_entries(const string& data_name,\
    const TimeInterval& tint)
  { return cdf_data_configmap->get_num_entries(data_name,tint);}
 
  
  DataBuffer_var get_data( const string& data_name );
  DataBuffer_var get_data( const string& data_name,
     const TimeInterval& time_interval );
     
  DataBuffer_var get_data_data( const string& data_name,
     const TimeInterval& time_interval, int entry=-1 );
  DataBuffer_var get_meta_data( const string& data_name );
  
  void get_time_range( TimeInterval& tint ) 
  { cdf_data_configmap->get_time_range(tint);}
  
  void get_time_range( const string& data_name, TimeInterval& tint ) 
  { cdf_data_configmap->get_time_range(data_name,tint);}

  bool is_data_available(const string& data_source_name,\
      const TimeInterval& tint);
  
  void set_numeric_ignoration_functor(
     string var_name, IgnoreNumericDataFunctor_var ignore_functor )
    { numeric_ignoration_table[var_name] = ignore_functor; }


}; // end CDFDataBaseDataSource

typedef Var<CDFDataBaseDataSource> CDFDataBaseDataSource_var;
inline Vostream& operator<<(Vostream& v_os,const CDFDataBaseDataSource& cdf_db)
{ v_os << cdf_db._dcm_file_name ; v_os << cdf_db.cdf_data_configmap; return v_os;}

inline Vistream& operator>>(Vistream& v_is, CDFDataBaseDataSource& cdf_db)
{ v_is >> cdf_db._dcm_file_name ; v_is >> cdf_db.cdf_data_configmap; return v_is;}

} // end namespace QDOS


#endif //  #ifndef Q_CDFDATABASEDATASOURCE_H
