#pragma once

#include <ArduinoJson.h>
#include "MeasurementData.hpp"
#include "SensorProtocol.hpp"
#include "SensorInformation.hpp"
#include <list>
#include <optional>
#include <string>
#include <utility>
#include <ErrorTypes.h>

// having the data be a struct of basic types makes sending easier,
// otherwise we would have to serialize the data before sending
class ClientDataPackage {
private:
    MeasurementData measurementData;
    SensorInformation sensorInformation;
    unsigned long timestamp; // maybe make this array

public:
    ClientDataPackage(MeasurementData value,
                      SensorInformation sensorInformation,

                      unsigned long timestamp)
            : measurementData(value),
              sensorInformation(sensorInformation),
              timestamp(timestamp) {
    }


    [[nodiscard]] const MeasurementData &
    getMeasurementData() const { return measurementData; }

    [[nodiscard]] const SensorInformation &
    getSensorInformation() const { return sensorInformation; }

    [[nodiscard]] unsigned long getTimestamp() const { return timestamp; }

    [[nodiscard]] std::string getDataPackageAsMinifiedJsonString() const {
        StaticJsonDocument<250> document; // 250 byte is the max send size of espnow

        document["hardwareName"] = sensorInformation.getHardwareNameString();
        document["timestamp"] = timestamp;
        document["sensorProtocol"] = sensorInformation.getProtocolString();
        document["value"] = measurementData.getValue();


        document["channel"] = measurementData.getChannel();


        document["i2cAddress"] = measurementData.getI2CAddress();

        document["measurementType"] = measurementData.getMeasurementTypeString();
        document["errorType"] = measurementData.getErrorTypeString();

        std::string jsonString;
        serializeJson(document, jsonString);
        return jsonString;
    }

    ClientDataPackage() : measurementData(MeasurementData(ERROR_VALUE, NO_CHANNEL, NO_I2C_ADDRESS,
                                                          MeasurementType::TEMPERATURE,
                                                          ErrorType::NULL_MESSAGE)),
                          sensorInformation(SensorInformation(HardwareName::NONE,
                                                              SensorProtocol::NULL_PROTOCOL)),
                          timestamp(0) {}
};