//
// This file hosts all the non-volatile configuration options for this node
//
#include <EEPROM.h>

#include "WiFiConfiguration.h"
#include "Utility.h"


ConfigManager::ConfigManager(const ConfigDefaults_t * _defaults) {
	(void)_defaults;
//	defaults = _defaults;
	COMPILER_ASSERT(sizeof(NVConfig_04_t) <= EEROM_SIZE);
	EEPROM.begin(EEROM_SIZE);			// Set for the max expected size
	// Here we could perform a 'load()' followed by a format check,
	// and it could then do a graceful update from one version to another,
	// and then commit it back to the rest of the program doesn't notice.
	int ret = load();
	switch (ret) {
		case MATCHING:
			// life is good, continue.
			break;
		case IS_OLDER:
			//if (getFormatVersion() == 3) {
			//	Upgrade();
			//	save();
			//} else {
			//	factoryReset();
			//	save();
			//}
			break;
		case IS_NEWER:
			// can't politely downgrade, so factory reset it.
		case IS_BROKEN:
		default:
//			factoryReset();		// Can't fix it, so factory reset it.
//			save();
			break;
	}
}

// Quite likely that this never runs...
ConfigManager::~ConfigManager() {
	EEPROM.end();
}


uint8_t ConfigManager::getFormatVersion() {
	return Configuration.format[0];
}

uint8_t * ConfigManager::getUserDataHandle() {
	return Configuration.userData;
}

int ConfigManager::getUserDataSize() {
	return USERSIZE;
}


void ConfigManager::factoryReset() {
	memset(&Configuration, 0, sizeof(NVConfig_04_t));		// Wipe them to be more secure
	Configuration.format[0] = EXPECTED_FMT;					//  put back the minimal
	Configuration.format[1] = ~EXPECTED_FMT;
	if (defaults) {
		strcpy(Configuration.info.name, defaults->name);
		strcpy(Configuration.info.UPDURL, defaults->UPDURL);
		strcpy(Configuration.info.NTPURL, defaults->NTPURL);
	}
	HexDump("factoryReset", (uint8_t *)&Configuration, sizeof(Configuration));
}


ConfigManager::FirmwareCheck_t ConfigManager::load() {
	uint8_t * ptr = (uint8_t *)&Configuration;
	size_t i = 0;
	do {
		*ptr++ = EEPROM.read(i++);
	} while (i < sizeof(Configuration));
//	if ((Configuration.format[0] & 0xFF) != (~Configuration.format[1] & 0xFF)) {
//		// Factory default
//		Serial.printf("Bad Configuration\n");
//		return IS_BROKEN;		// Fatal and restored to factory default.
//	} else if (Configuration.format[0] < EXPECTED_FMT) {
//		Serial.printf("Old Configuration. It needs an update!\n");
//		return IS_OLDER;
//	} else if (Configuration.format[0] > EXPECTED_FMT) {
//		Serial.printf("Too new a configuration.\n");
//		return IS_NEWER;
//	}
	Serial.printf("Loading from EEROM\n");
	Serial.printf("Node Name: %s\n", Configuration.info.name);
	Serial.printf("SSID: %s\n", Configuration.info.ssid);
	Serial.printf("PASS: %s\n", Configuration.info.pass);
	Serial.printf("URL : %s\n", Configuration.info.UPDURL);
	Serial.printf("NTP : %s\n", Configuration.info.NTPURL);
	HexDump("After Load", (uint8_t *)&Configuration, sizeof(Configuration));
//	//delay(500);
	return MATCHING;	// no error
}


void ConfigManager::save(void) {
	uint8_t * ptr = (uint8_t *)&Configuration;
	size_t i = 0;
	do {
		EEPROM.write(i++, *ptr++);
	} while (i < sizeof(Configuration));
	if (EEPROM.commit()) {
		Serial.printf("EEPROM.commit() success.\n");
	} else {
		Serial.printf("EEPROM.commit() FAILED !!!!!!!! FAILED !!!!!!!! FAILED !!!!!!!!\n");
	}
	HexDump("After Save", (uint8_t *)&Configuration, sizeof(Configuration));
	//delay(500);
}


String ConfigManager::getNTPServerName() {
	return String(Configuration.info.NTPURL);
}
void ConfigManager::setNTPServerName(String _name) {
	strncpy(Configuration.info.NTPURL, _name.c_str(), sizeof(Configuration.info.NTPURL));
	Serial.printf("setNTPServerName(%s)\n", Configuration.info.NTPURL);
}

String ConfigManager::getName() {
	return String(Configuration.info.name);
}

void ConfigManager::setName(String _name) {
	strncpy(Configuration.info.name, _name.c_str(), sizeof(Configuration.info.name));
	Serial.printf("setName(%s)\n", Configuration.info.name);
}

String ConfigManager::getSSID() {
	return String(Configuration.info.ssid);
}

void ConfigManager::setSSID(String _ssid) {
	strncpy(Configuration.info.ssid, _ssid.c_str(), sizeof(Configuration.info.ssid));
	Serial.printf("setSSID(%s)\n", Configuration.info.ssid);
}

String ConfigManager::getPassword() {
	return String(Configuration.info.pass);
}

void ConfigManager::setPassword(String _password) {
	strncpy(Configuration.info.pass, _password.c_str(), sizeof(Configuration.info.pass));
	Serial.printf("setPass(%s)\n", Configuration.info.pass);
}

String ConfigManager::getURL() {
	return String(Configuration.info.UPDURL);
}

void ConfigManager::setURL(String _url) {
	strncpy(Configuration.info.UPDURL, _url.c_str(), sizeof(Configuration.info.UPDURL));
	Serial.printf("setURL (%s)\n", Configuration.info.UPDURL);
}

