/**
 * @file gps.cpp
 *
 * @brief Implementation file for GPS-related functions in the ChainLube application.
 *
 * This file contains the implementation of functions related to GPS functionality within the ChainLube
 * application. It includes the initialization of the GPS module, processing GPS data for wheel speed,
 * and maintaining Diagnostic Trouble Codes (DTCs) based on GPS communication status.
 *
 * @author Marcel Peterkau
 * @date   09.01.2024
 */

#include "gps.h"

TinyGPSPlus gps;

/**
 * @brief Initializes the GPS module with the specified baud rate.
 *
 * This function initializes the GPS module with the baud rate configured in the application settings.
 * It also prints a debug message indicating the initialization status.
 */
void Init_GPS()
{
    uint32_t baudrate;
    switch (LubeConfig.GPSBaudRate)
    {
    case BAUD_9600:
        baudrate = 9600;
        break;
    case BAUD_115200:
        baudrate = 115200;
        break;
    default:
        baudrate = 4800;
        break;
    }

    Debug_pushMessage(PSTR("Init GPS with Baud %d\n"), baudrate);
    Serial.begin(baudrate);
}

/**
 * @brief Processes GPS data to calculate rear wheel speed and returns the distance traveled.
 *
 * This function processes GPS data received from the GPS module, calculates the rear wheel speed in
 * kilometers per hour, and returns the distance traveled based on the speed and time elapsed since
 * the last valid speed measurement.
 *
 * @return The distance traveled in millimeters since the last GPS speed measurement.
 */
uint32_t Process_GPS_WheelSpeed()
{
    static uint32_t lastRecTimestamp;
    static uint32_t lastValidSpeedTimestamp;
    uint16_t RearWheelSpeed_kmh;

    while (Serial.available() > 0)
    {
        uint8_t incoming = Serial.read();
        if (gps.encode(incoming))
        {
            RearWheelSpeed_kmh = gps.speed.isValid() ? gps.speed.kmph() : 0;

            if (RearWheelSpeed_kmh > 0)
            {
                uint32_t RWP_millimeter_per_second = ((uint32_t)RearWheelSpeed_kmh * 1000000) / 3600;

                uint32_t timesincelast = millis() - lastValidSpeedTimestamp;
                lastValidSpeedTimestamp = millis();

                uint32_t milimeters_to_add = (RWP_millimeter_per_second * timesincelast) / 1000;

                return milimeters_to_add;
            }
            lastRecTimestamp = millis();
        }
    }

    // Maintain DTC for no GPS data received within a certain time frame
    MaintainDTC(DTC_NO_GPS_SERIAL, (millis() > lastRecTimestamp + 10000));

    return 0;
}
