// C++ code Copyright (C) David R. Evans G4AMJ/NQ0I

#ifndef GMDRH
#define GMDRH

// all the data handling inside MIDAS is in terms of "generic MIDAS
// data records" (GMDRs). Every real, live data format must be able
// to be cast to a gmdr. Every real, live file type must be able to
// read a record and produce a gmdr.

#include <data.h>

// the list of classes from which conversion can be made
class bdr_record;
class edr_record;
class pdsdr_record;
class science_edr_record;

class GMDR : public data_record   // it's important, so it goes in caps!
{ class GMDR_datum_struct
  { friend class GMDR;

    byte _polarisation;      // 0 = left, 1 = right
    uint16 _datum;

    public:
      GMDR_datum_struct(void) : _polarisation(0), _datum(0) { }
  };

  class GMDR_status_struct
  { friend class GMDR;

    byte _frequency, _pra_mode, _pra_submode;
    uint32 _fixlo_frequency;

  public:
    GMDR_status_struct(void) : _fixlo_frequency(0), _pra_mode(0),
                               _pra_submode(0)
      { }
    reveal(uint32, fixlo_frequency, _fixlo_frequency);
    reveal(int, frequency, _frequency);
    reveal(int, pra_mode, _pra_mode);
    reveal(int, pra_submode, _pra_submode);
  };

  boolean _is_science, _binnable;
  byte _min_channel, _max_channel, _n_sweeps, _sc_mode;
  GMDR_datum_struct* _data;
  int _sweep_duration;
  uint16 _mode_command, _configuration_command;
  GMDR_status_struct* _stati;

  void _initialise(void);

public:
  GMDR(void);
  GMDR(const GMDR&);
  ~GMDR(void)
  { destroy_array(_data);
    destroy_array(_stati);
  }

  void operator=(const bdr_record&);
  void operator=(const edr_record&);
  void operator=(const pdsdr_record&);
  void operator=(const science_edr_record&);

  reveal(uint16, configuration_command, _configuration_command);
  reveal(boolean, is_science, _is_science);
  reveal(boolean, binnable, _binnable);
  reveal(int, min_channel, _min_channel);
  reveal(int, max_channel, _max_channel);
  reveal(uint16, mode_command, _mode_command);
  reveal(int, n_sweeps, _n_sweeps);
  reveal(int, n_channels, _max_channel - _min_channel + 1);
  reveal(int, sc_mode, _sc_mode);
  reveal(int, sweep_duration, _sweep_duration);

  byte polarisation(const int sweep, const int channel) const;
  uint16 datum(const int sweep, const int channel) const;

// frequency of a given GS-8 scan (times 10)
  uint32 fixlo_frequency(const int n_sweep) const
    { return _stati[n_sweep - 1]._fixlo_frequency; }

// is a particular sweep fixlo?
  inline boolean fixlo(const int s) const
   { return ((pra_submode(s) == fixlol) || (pra_submode(s) == fixloh)); }
  inline int pra_mode(const int n_sweep) const
    { return _stati[n_sweep - 1].pra_mode(); }
  inline int pra_submode(const int n_sweep) const
    { return _stati[n_sweep - 1].pra_submode(); }
  inline const char* pra_submode_name(const int n_sweep) const
    { return _pra_submode_name[pra_submode(n_sweep)]; }

// is this a VIM mode record?
  inline boolean vim(void) const
    { return ((sc_mode() == cr5a) || (sc_mode() == uv5a)); }
  inline int frequency(const int n_sweep) const
    { return _stati[n_sweep - 1].frequency(); }

};



#endif
