#include "ConfigData.hpp"

#include <iostream>
#include <sstream>
#include <string>
#include <sstream>
#include <vector>

#include "FileSys.hpp"

// Serialization Library headers
#include <cereal/cereal.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>

#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/chrono.hpp>

struct ConfigDataStruct
{
	std::string SerialNum;
	std::string SWVerNum;
	float recoveryBelPos_pctFull;
	float surfaceOpsBelPos_pctFull;

	template <class Archive>
		void serialize(Archive& configFileArchive)
		{
			configFileArchive(SerialNum, SWVerNum, recoveryBelPos_pctFull, surfaceOpsBelPos_pctFull);
		}
};

static ConfigDataStruct cpfConfigData;

float ConfigData::getSubmergePumpSpeed_pctMax()
{
	return 0.4;
}

void ConfigData::readConfigData()
{	
	// TODO: need a cpfAssert or recovery or default to safe configData file?
	std::stringstream configFileStream;
	
	configFileStream = FileSys::readFile("/ConfigDataJSON.crl");

	cereal::JSONInputArchive iarchive(configFileStream);
	iarchive(cpfConfigData);
	
	std::cout << "ConfigData.SerialNum: " << getSN() << std::endl;
	std::cout << "ConfigData.SWVerNum: " << getSWVerNum() << std::endl;
	std::cout << "ConfigData.recoveryBelPos: " << getRecoveryBelPos_pctFull() << std::endl;
	std::cout << "ConfigData.surfaceOpsBelPos: " << getSurfaceOpsBelPos_pctFull() << std::endl;
}

void ConfigData::writeConfigData()
{
	std::stringstream configFileStream;

	{
		cereal::JSONOutputArchive oarchive(configFileStream);
		oarchive(cpfConfigData);
	}
	
	std::string configFileString{configFileStream.str()};
	
	const char* configFileChars = configFileString.c_str();
	
	//SDLogger::writeFile("./ConfigDataJSON.crl", configFileChars, configFileString.length());
}

std::string ConfigData::getSN()
{
	return cpfConfigData.SerialNum;
}	

std::string ConfigData::getSWVerNum()
{
	return cpfConfigData.SerialNum;
}	

float ConfigData::getSurfaceOpsBelPos_pctFull()
{
	return cpfConfigData.surfaceOpsBelPos_pctFull;
}	

void ConfigData::setSurfaceOpsBelPos_pctFull(float newValue)
{
	//This needs to be done with a range of floating point values around the desired value
	//Check for valid values
	if (newValue != cpfConfigData.surfaceOpsBelPos_pctFull)
	{
		cpfConfigData.surfaceOpsBelPos_pctFull = newValue;
		writeConfigData();
	}
}	

float ConfigData::getRecoveryBelPos_pctFull()
{
	return cpfConfigData.recoveryBelPos_pctFull;
}

void ConfigData::setRecoveryBelPos_pctFull(float newValue)
{
	cpfConfigData.recoveryBelPos_pctFull = newValue;
}