#pragma once

#include <Arduino.h>
#include "Config.h"
#include "GnssTypes.h"

namespace field_qa {

class GnssManager {
 public:
  void begin();
  void poll();
  bool probeAtStartup(Stream& serialOut);
  GnssSample makeSample() const;
  size_t copySatellites(SatelliteInfo* out, size_t maxCount) const;
  const char* detectedChipName() const;

 private:
  void startUart(uint32_t baud, int rxPin, int txPin);
  bool probeAtBaud(uint32_t baud, int rxPin, int txPin);
  bool collectTraffic(uint32_t windowMs);
  void processNmeaLine(char* line);
  void parseGga(char* fields[], int count);
  void parseGsa(char* fields[], int count);
  void parseGsv(char* fields[], int count);
  void parseRmc(char* fields[], int count);
  void parseVtg(char* fields[], int count);
  void parseTxt(char* fields[], int count);
  int splitCsvPreserveEmpty(char* line, char* fields[], int maxFields);
  static bool parseUInt2(const char* s, uint8_t& out);
  static double parseNmeaCoord(const char* value, const char* hemi);
  void clearSatelliteView();
  void clearTalkerSatellites(const char* talker);
  void finalizeSatelliteStats();
  void addUsedPrn(uint8_t prn);
  bool prnUsedInSolution(uint8_t prn) const;

  HardwareSerial m_serial{1};
  char m_line[160] = {0};
  size_t m_lineLen = 0;
  char m_detectedChip[16] = {0};
  bool m_sawSentence = false;
  bool m_seenUbloxPubx = false;
  bool m_hasPps = false;

  GnssSample m_state;
  SatelliteInfo m_satellites[kMaxSatellites];
  uint8_t m_usedPrns[kMaxSatellites] = {0};
  size_t m_usedPrnCount = 0;
  size_t m_satCount = 0;
  uint32_t m_lastGsaMs = 0;
  uint32_t m_lastGsvMs = 0;
  uint32_t m_lastFixMs = 0;
  uint32_t m_bootMs = 0;
};

}  // namespace field_qa
