/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2022, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#pragma once

#include <mrpt/math/CMatrixFixed.h>

#include "gnss_messages_common.h"

namespace mrpt::obs::gnss
{
/** GPS datum for TopCon's mmGPS devices: PZS. \sa mrpt::obs::CObservationGPS */
struct Message_TOPCON_PZS : public gnss_message
{
	/** Static msg type (member expected by templates) */
	enum
	{
		msg_type = TOPCON_PZS
	};

	/** The measured latitude, in degrees (North:+ , South:-) */
	double latitude_degrees{0};
	/** The measured longitude, in degrees (East:+ , West:-) */
	double longitude_degrees{0};
	/** ellipsoidal height from N-beam [m] perhaps weighted with regular gps */
	double height_meters{0};
	/** ellipsoidal height [m] without N-beam correction */
	double RTK_height_meters{0};
	/** position SEP [m] */
	float PSigma{0};
	/** Vertical angle of N-beam */
	double angle_transmitter{0};
	/** ID of the transmitter [1-4], 0 if none. */
	uint8_t nId{0};
	/** 1: GPS, 2: mmGPS */
	uint8_t Fix{0};
	/** battery level on transmitter */
	uint8_t TXBattery{0};
	/** battery level on receiver */
	uint8_t RXBattery{0};
	uint8_t error{0};  //! system error indicator

	bool hasCartesianPosVel{false};
	/** Only if hasCartesianPosVel is true */
	double cartesian_x{0}, cartesian_y{0}, cartesian_z{0};
	/** Only if hasCartesianPosVel is true */
	double cartesian_vx{0}, cartesian_vy{0}, cartesian_vz{0};

	bool hasPosCov{false};
	/** Only if hasPosCov is true */
	mrpt::math::CMatrixFloat44 pos_covariance;

	bool hasVelCov{false};
	/** Only if hasPosCov is true */
	mrpt::math::CMatrixFloat44 vel_covariance;

	bool hasStats{false};
	uint8_t stats_GPS_sats_used{0},
		stats_GLONASS_sats_used{0};	 //<! Only if hasStats is true
	/** [0,100] %, only in modes other than RTK FIXED. */
	uint8_t stats_rtk_fix_progress{0};

	Message_TOPCON_PZS();
	/**  Return the geodetic coords as a mrpt::topography::TGeodeticCoords
	 * structure (requires linking against mrpt-topography)
	 *   Call as: getAsStruct<TGeodeticCoords>(); */
	template <class TGEODETICCOORDS>
	inline TGEODETICCOORDS getAsStruct() const
	{
		return TGEODETICCOORDS(
			latitude_degrees, longitude_degrees, height_meters);
	}
	void dumpToStream(std::ostream& out) const override;  // See docs in base

   protected:
	void internal_writeToStream(
		mrpt::serialization::CArchive& out) const override;
	void internal_readFromStream(mrpt::serialization::CArchive& in) override;

   public:
};

/** TopCon mmGPS devices: SATS, a generic structure for statistics about tracked
 * satelites and their positions. \sa mrpt::obs::CObservationGPS   */
struct Message_TOPCON_SATS : public gnss_message
{
	/** Static msg type (member expected by templates) */
	enum
	{
		msg_type = TOPCON_SATS
	};

	Message_TOPCON_SATS();

	/** The list of USI (Universal Sat ID) for the detected sats (See GRIL
	 * Manual, pag 4-31). */
	std::vector<uint8_t> USIs;
	/** Elevation (in degrees, 0-90) for each satellite in USIs. */
	std::vector<int8_t> ELs;
	/** Azimuth (in degrees, 0-360) for each satellite in USIs. */
	std::vector<int16_t> AZs;

	void dumpToStream(std::ostream& out) const override;  // See docs in base
   protected:
	void internal_writeToStream(
		mrpt::serialization::CArchive& out) const override;
	void internal_readFromStream(mrpt::serialization::CArchive& in) override;
};
}  // namespace mrpt::obs::gnss
