#include <networkAbstractionLayer.h>
#include <PontCoopScheduler.h>
#include <iwdg.h>
#include <logger.h>
#include <sinkStruct.h>
#include <config.h>

#include <networkAbstractionLayer_impl.h>


const uint16_t SINK_PORT = 20169;

static t_seconds seconds = { .seconds = 0, .missedUpdates = 0, .valid = false };
static t_configBlock *config;


static void networkSecondsHandler(void *handle) {
    static bool tryAgain = false;

    seconds.seconds += 1;

    if (! seconds.valid) {
        coloredMsg(LOG_YELLOW, "nsh, initially querying time");
        uint64_t tmpSeconds = networkSntpQuery();
        if (tmpSeconds != 0) {
            coloredMsg(LOG_YELLOW, "nsh, success, time is %lu", tmpSeconds);
            seconds.seconds = tmpSeconds;
            seconds.missedUpdates = 0;
            seconds.valid = true;
        } else {
            coloredMsg(LOG_YELLOW, "nsh, failed");
            seconds.missedUpdates += 1;
        }
    } else if (tryAgain || ((seconds.seconds % 300) == 0)) {
        coloredMsg(LOG_YELLOW, "nsh, periodically querying time");
        uint64_t tmpSeconds = networkSntpQuery();
        if (tmpSeconds != 0) {
            coloredMsg(LOG_YELLOW, "nsh, success, network time is %lu", tmpSeconds);
            seconds.missedUpdates = 0;
            tryAgain = false;
            if (seconds.seconds != tmpSeconds) {
                coloredMsg(LOG_YELLOW, "nsh, local time updated");
                seconds.seconds = tmpSeconds;
            } else {
                coloredMsg(LOG_YELLOW, "nsh, local time still in sync");
            }
        } else {
            coloredMsg(LOG_YELLOW, "nsh, failed, trying again ...");
            seconds.missedUpdates += 1;
            tryAgain = true;
        }
    }

    HAL_IWDG_Refresh(&hiwdg);
}

t_seconds* networkGetSeconds() {
    return &seconds;
}

int8_t networkSendMinuteBuffer(t_minuteBuffer *minuteBuffer) {
    return networkUdpSend(config->sinkServer, SINK_PORT, minuteBuffer->b, sizeof(minuteBuffer->b));
}

void networkInit() {
    networkImplInit();

    config = getConfig();
    schAdd(networkSecondsHandler, NULL, 0, 1000);
}