/**********************************************************************************************
    Copyright (C) 2018 Oliver Eichler <oliver.eichler@gmx.de>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

**********************************************************************************************/

#ifndef CRTGPSINFO_H
#define CRTGPSINFO_H

#include <QTcpSocket>
#include <QWidget>
#include <functional>

#include "realtime/IRtInfo.h"
#include "ui_IRtGpsTetherInfo.h"

class CRtGpsTether;
class QSettings;

class CRtGpsTetherInfo : public IRtInfo, private Ui::IRtGpsTetherInfo {
  Q_OBJECT
 public:
  CRtGpsTetherInfo(CRtGpsTether& source, QWidget* parent);
  virtual ~CRtGpsTetherInfo();

  void loadSettings(QSettings& cfg);
  void saveSettings(QSettings& cfg) const;

  QPointF getPosition() const;
  qreal getHeading() const;
 signals:
  void sigChanged();

 private slots:
  void slotHelp() const;
  void slotConnect(bool yes);
  void slotConnected();
  void slotDisconnected();
  void slotError(QAbstractSocket::SocketError socketError);
  void slotReadyRead();
  void slotUpdate();

 private:
  bool verifyLine(const QString& line);
  void disconnectFromHost();
  void autoConnect(int msec);

  using fNemaLine = std::function<void(const QStringList&)>;
  fNemaLine nmeaDefault = [&](const QStringList& t) { qDebug() << t[0] << "unknown"; };

  void nmeaGSV(const QStringList& tokens);
  void nmeaRMC(const QStringList& tokens);
  void nmeaGGA(const QStringList& tokens);
  void nmeaVTG(const QStringList& tokens);
  void nmeaGSA(const QStringList& tokens);

 private:
  void startRecord(const QString& filename) override;
  void fillTrackData(CTrackData& data) override;

  void changeEvent(QEvent* e) override;
  void updateStatusLabel();

  /** @brief Last socket error, empty when there is none. Unformatted, so it can be re-themed. */
  QString errorMessage;

  QTcpSocket* socket;
  QTimer* timer;

  QHash<QString, fNemaLine> dict;

  QDateTime lastTimestamp;

  struct rmc_t {
    bool isValid{false};
    QDateTime datetime;
    qreal lat{0.0};
    qreal lon{0.0};
    qreal groundSpeed{0.0};
    qreal trackMadeGood{0.0};
    qreal magneticVariation{0.0};
  };

  rmc_t rmc;

  struct gga_t {
    bool isValid{false};
    QDateTime datetime;
    qreal lat{0.0};
    qreal lon{0.0};
    qint32 quality{-1};
    qint32 numSatelites{0};
    qreal horizDilution{0.0};
    qreal altAboveSeaLevel{0.0};
    qreal geodialSeparation{0.0};
    qreal age{0};
    qint32 diffRefStation{0};
  };

  gga_t gga;

  struct vtg_t {
    bool isValid{false};
    qreal trackDegreesTrue{0.0};
    qreal trackDegreesMagnetic{0.0};
    qreal speedKnots{0.0};
    qreal speedMeters{0.0};
  };

  vtg_t vtg;

  struct gsa_t {
    bool isValid{false};
    int fix{0};
    qreal hdop{0.0};
    qreal vdop{0.0};
  };

  gsa_t gsa;
};

#endif  // CRTGPSINFO_H
