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

#define EEROM_SIZE 512

// Change this when it is required to force a reinitialization
// 
#define EXPECTED_FMT 0x03        

typedef struct {
  uint8_t format[2];          // Format of this data structure, and ~format
  struct info {
    char name[CFG_NAMESIZE];    // Network Discoverable Name of this node
    char ssid[CFG_SSIDSIZE];    // SSID of the saved network [max length defined by standard]
    char pass[CFG_PASSSIZE];    // PASScode of the saved network
    char updateURL[CFG_UURLSIZE]; // URL of the trusted server with code updates
    uint16_t onRef;         // A/D reference above which the output is considered 'On'
    uint16_t offRef;        // A/D reference below which the output is considered 'Off'
    uint16_t autoOff;       // When non-zero, this is the # minutes until auto-turn off
    //char NTPIP[64];       // Name or IP of the NTP Server
    char Padding[10];
  } info;
} Config_t;
#define OFS_FORMAT  (0)
#define OFS_NAME  (OFS_FORMAT + 2)
#define OFS_SSID  (OFS_NAME + CFG_NAMESIZE)
#define OFS_PASS  (OFS_SSID + CFG_SSIDSIZE)
#define OFS_URL   (OFS_PASS + CFG_PASSSIZE)
#define OFS_ONREF (OFS_URL + CFG_UURLSIZE)
#define OFS_OFFREF  (OFS_ONREF + sizeof(uint16_t))
#define OFS_AUTOOFF (OFS_OFFREF + sizeof(uint16_t))
//#define OFS_NTPIP (OFS_OFFREF + 2)

Config_t Configuration;

ConfigManager::ConfigManager() {

}

void ConfigManager::factoryReset() {
  Configuration.format[0] = EXPECTED_FMT;
  Configuration.format[1] = ~EXPECTED_FMT;
  strcpy(Configuration.info.name, "3-Way Switch");
  Configuration.info.ssid[0] = '\0';
  Configuration.info.pass[0] = '\0';
  //Configuration.info.updateURL[0] = '\0';
  strcpy(Configuration.info.updateURL, "https://192.168.1.201/mbed/ESP.php");
  Configuration.info.onRef = 150;
  Configuration.info.offRef = 100;
  Configuration.info.autoOff = 0;
  //Configuration.info.NTPIP[0] = '\0';
}

void ConfigManager::load() {
  EEPROM.begin(512);
  uint8_t * ptr = (uint8_t *) &Configuration;
  uint8_t i = 0;
  do {
    *ptr++ = EEPROM.read(OFS_FORMAT + i++);
  } while (i < sizeof(Configuration));
  if ((Configuration.format[0] & 0xFF) != (~Configuration.format[1] & 0xFF)) {
    // Factory default
    Serial.printf("Bad Configuration - reset to factory defaults\n");
    factoryReset();
    return;
  }
  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.updateURL);
  Serial.printf("On   Ref: %d\n", Configuration.info.onRef);
  Serial.printf("Off  Ref: %d\n", Configuration.info.offRef);
  Serial.printf("Auto Off: %d\n", Configuration.info.autoOff);
  //Serial.printf("NTP Svr: %s\n", Configuration.info.NTPIP);
  delay(500);
}

void ConfigManager::save(void) {
  EEPROM.begin(512);
  uint8_t * ptr = (uint8_t *) &Configuration;
  uint8_t i = 0;
  do {
    EEPROM.write(OFS_FORMAT + i++, *ptr++);
  } while (i < sizeof(Configuration));
  EEPROM.commit();
  delay(500);
}

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

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.updateURL);
}

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

uint16_t ConfigManager::getOnRef() {
  return Configuration.info.onRef;
}
void ConfigManager::setOnRef(uint16 onR) {
  Configuration.info.onRef = onR;
}
uint16_t ConfigManager::getOffRef() {
  return Configuration.info.offRef;
}
void ConfigManager::setOffRef(uint16 offR) {
  Configuration.info.offRef = offR;
}
uint16_t ConfigManager::getAutoOff() {
  return Configuration.info.autoOff;
}
void ConfigManager::setAutoOff(uint16 autoOff) {
  Configuration.info.autoOff = autoOff;
}
