#ifndef SATOBS_H
#define SATOBS_H

#include <string>
#include <map>
#include <newmat.h>
#include "pppInclude.h"
#include "bnctime.h"

namespace BNC_PPP {

class t_pppStation;

class t_pppSatObs {
 public:
  t_pppSatObs(const t_satObs& satObs);
  ~t_pppSatObs();
  bool                isValid() const {return _valid;}
  void                prepareObs();
  const t_prn&        prn() const {return _prn;}
  const ColumnVector& xc() const {return _xcSat;}
  const bncTime&      time() const {return _time;}
  t_irc               cmpModel(const t_pppStation* station);
  double              obsValue(t_lc::type tLC) const;
  double              cmpValue(t_lc::type tLC) const;
  double              cmpValueForBanc(t_lc::type tLC) const;
  double              rho() const {return _model._rho;}
  double              sagnac() const {return _model._sagnac;}
  double              eleSat() const {return _model._eleSat;}
  bool                modelSet() const {return _model._set;}
  void                printModel() const;
  double              lc(t_lc::type tLC, double L1, double L2, 
                         double C1, double C2, ColumnVector* coeff = 0) const;
  double              lambda(t_lc::type tLC) const;
  double              sigma(t_lc::type tLC) const;
  double              maxRes(t_lc::type tLC) const;
  bool                outlier() const {return _outlier;}
  void                setOutlier() {_outlier = true;}
  int                 channel() const {return _channel;}
  void                setRes(t_lc::type tLC, double res);
  double              getRes(t_lc::type tLC) const;

  bool slip() const {
    for (unsigned ii = 0; ii < _allObs.size(); ii++) {
      if (_allObs[ii]->_slip) {
        return true;
      }
    }
    return false;
  }

  int slipCounter() const {
    int cnt = -1;
    for (unsigned ii = 0; ii < _allObs.size(); ii++) {
      if (_allObs[ii]->_slipCounter > cnt) {
        cnt = _allObs[ii]->_slipCounter;
      }
    }
    return cnt;
  }

  int biasJumpCounter() const {
    int jmp = -1;
    for (unsigned ii = 0; ii < _allObs.size(); ii++) {
      if (_allObs[ii]->_biasJumpCounter > jmp) {
        jmp = _allObs[ii]->_biasJumpCounter;
      }
    }
    return jmp;
  }

 private:
  class t_model {
   public:
    t_model() {reset();}
    ~t_model() {}
    void reset() {
      _set     = false;
      _rho     = 0.0;
      _eleSat  = 0.0;
      _azSat   = 0.0;
      _recClkM = 0.0;
      _satClkM = 0.0;
      _sagnac  = 0.0;
      _antEcc  = 0.0;
      _tropo   = 0.0;
      _tide    = 0.0;
      _windUp  = 0.0;
      _antPco1 = 0.0;
      _antPco2 = 0.0;
      _biasC1  = 0.0;
      _biasC2  = 0.0;
      _biasL1  = 0.0;
      _biasL2  = 0.0;
    }
    bool   _set;
    double _rho;
    double _eleSat;
    double _azSat;
    double _recClkM;
    double _satClkM;
    double _sagnac;
    double _antEcc;
    double _tropo;
    double _tide;
    double _windUp;
    double _antPco1;
    double _antPco2;
    double _biasC1;
    double _biasC2;
    double _biasL1;
    double _biasL2;
  };

  t_prn                        _prn;
  bncTime                      _time;
  int                          _channel;
  std::vector<t_frqObs*>       _allObs;
  bool                         _valid;
  t_frqObs*                    _validObs1;
  t_frqObs*                    _validObs2;
  double                       _f1;
  double                       _f2;
  double                       _rawC1;
  double                       _rawC2;
  double                       _rawL1;
  double                       _rawL2;
  ColumnVector                 _xcSat;
  ColumnVector                 _vvSat;
  t_model                      _model;
  bool                         _outlier;
  std::map<t_lc::type, double> _res;
};

}

#endif
