#ifndef PPP_H
#define PPP_H

#include <string>
#include <vector>

#include "bncconst.h"
#include "bnctime.h"
#include "t_prn.h"

namespace BNC {

class pppExcept {
 public:
  pppExcept(const char* msg) {
    _msg = msg;
  }
  ~pppExcept() {}
  std::string what() {return _msg;}
 private:
  std::string _msg;
};

enum e_pppMode {
  mode_PPP_DF,
  mode_SPP_DF,
  mode_PPP_SF,
  mode_SPP_SF,
};

class t_output {
 public:
  bncTime      _epoTime;           
  double       _xyzRover[3];  
  double       _covMatrix[6]; 
  int          _numSat;       
  double       _pDop;         
  std::string  _log;          
  bool         _error;        
};

class t_pppObs  {
 public:
  t_pppObs() {
    _code            = 0.0;          
    _codeValid       = false;     
    _phase           = 0.0;         
    _phaseValid      = false;    
    _doppler         = 0.0;       
    _dopplerValid    = false;  
    _snr             = 0.0;           
    _snrValid        = false;      
    _slip            = false;          
    _slipCounter     = 0;   
    _biasJumpCounter = 0;
  }
  std::string _rnxType2ch; 
  double      _code;          
  bool        _codeValid;     
  double      _phase;         
  bool        _phaseValid;    
  double      _doppler;       
  bool        _dopplerValid;  
  double      _snr;           
  bool        _snrValid;      
  bool        _slip;          
  int         _slipCounter;   
  int         _biasJumpCounter;
};

class t_pppSatObs {
 public:
  t_pppSatObs() {}
  ~t_pppSatObs() {for (unsigned ii = 0; ii < _obs.size(); ii++) delete _obs[ii];}
  t_prn                  _prn;
  bncTime                _time;
  std::vector<t_pppObs*> _obs;
};

class t_orbCorr {
 public:
  t_prn          prn() const {return _prn;}
  unsigned short IOD() const {return _iod;}
  t_prn          _prn;
  unsigned short _iod;
  bncTime        _time;
  char           _system;
  double         _xr[3];
  double         _dotXr[3];
};

class t_clkCorr {
 public:
  t_prn          prn() const {return _prn;}
  unsigned short IOD() const {return _iod;}
  t_prn          _prn;
  unsigned short _iod;
  bncTime        _time;
  double         _dClk;
  double         _dotDClk;
  double         _dotDotDClk;
  double         _clkPartial;
};

class t_bias {
 public:
  std::string _rnxType3ch;
  double      _value;
};

class t_satBiases {
 public:
  t_prn               _prn;
  bncTime             _time;
  int                 _nx;
  int                 _jumpCount;
  std::vector<t_bias> _biases;
};

enum e_tropoModel{tropoModel_NO, tropoModel_SAAST, tropoModel_MARINI, 
                  tropoModel_HOPF, tropoModel_UNB3M};

enum e_tropoMF{tropoMF_INTRINSIC, tropoMF_COSZ, tropoMF_NIELL_DRY, 
               tropoMF_NIELL_WET, tropoMF_HOPF, tropoMF_GMF_DRY, 
               tropoMF_GMF_WET, tropoMF_GMF_COMB};

class t_frequency {
 public:
  enum type {dummy = 0, G1, G2, R1, R2, maxFr};

  static std::string toString(type tt) {
    if      (tt == G1) return "G1";
    else if (tt == G2) return "G2";
    else if (tt == R1) return "R1";
    else if (tt == R2) return "R2";
    return std::string();
  }
};

class t_lc {
 public:
  enum type {dummy = 0, l1, l2, c1, c2, lIF, cIF, MW, CL, maxLc};

  static bool need2ndFreq(type tt) {
    if (tt == l2 || tt == c2 || tt == lIF || tt == cIF || tt == MW) return true;
    return false;
  }  

  static bool includesPhase(type tt) {
    if (tt == l1 || tt == l2 || tt == lIF || tt == MW || tt == CL) return true;
    return false;
  }

  static bool includesCode(type tt) {
    if (tt == c1 || tt == c2 || tt == cIF || tt == MW || tt == CL) return true;
    return false;
  }

  static std::string toString(type tt) {
    if      (tt == l1)  return "l1";
    else if (tt == l2)  return "l2";
    else if (tt == c1)  return "c1";
    else if (tt == c2)  return "c2";
    else if (tt == lIF) return "lIF";
    else if (tt == cIF) return "cIF";
    else if (tt == MW)  return "MW";
    else if (tt == CL)  return "CL";
    return std::string();
  }
};

} // namespace BNC

#endif
