
void deleteConfig()
{
  snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_deleting);
  sendLog(logBuf);

  FS_format();
  delay(100);
  ESP.restart();
}



void loadConf_all()
{
  snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_loading);
  sendLog(logBuf);

  loadConf_Secrets();

  loadConf_DevWiFi();
  loadConf_Web();
  loadConf_Mqtt();
  
  #ifdef FIRMWARE_VARIANT_THERMOSTAT
    loadConf_Therm();
  #endif

  #ifdef FIRMWARE_VARIANT_HEATCONTROL
    loadConf_Heatc();
  #endif

  loadConf_Add();

  #ifdef ENABLE_FEATURE_NTP_TIME
    loadConf_Time();
  #endif

  loadConf_Log();
  loadConf_Sens();
  
  snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_loading_done);
  sendLog(logBuf);
}



bool conf_getDebugMode()
{
  uint8_t _data;
  EEPROM.begin(EEPROM_SIZE);
  _data = EEPROM.read(EEPROM_ADDR_DEBUGMODE);
  EEPROM.end();
  if(_data == 1) return true;
  else return false;
}

void conf_restoreDebugMode()
{
  if(conf_getDebugMode()) debug = true;
  else debug = false;
}

void conf_setDebugMode()
{
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.write(EEPROM_ADDR_DEBUGMODE, 1);
  EEPROM.commit();
  EEPROM.end();
  debug = true;
}

void conf_clearDebugMode()
{
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.write(EEPROM_ADDR_DEBUGMODE, 0);
  EEPROM.commit();
  EEPROM.end();
  debug = false;
}


void saveConfig_all() {
  saveConfig_all(false);
}
void saveConfig_all(bool _force)
{
  if(confCheckUnsaved() || _force) {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_saving);
    sendLog(logBuf);

    saveConf_Secrets(_force);
    
    yield();
    saveConf_DevWiFi(_force);
    yield();
    saveConf_Web(_force);
    yield();
    saveConf_Mqtt(_force);
    yield();

    #ifdef FIRMWARE_VARIANT_THERMOSTAT
    saveConf_Therm(_force);
    yield();
    #endif

    #ifdef FIRMWARE_VARIANT_HEATCONTROL
    saveConf_Heatc(_force);
    yield();
    #endif

    saveConf_Add(_force);
    yield();

    #ifdef ENABLE_FEATURE_NTP_TIME
    saveConf_Time(_force);
    yield();
    #endif

    saveConf_Log(_force);
    yield();
    saveConf_Sens(_force);
    yield();

    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_saveToFS_done);
    sendLog(logBuf);
  }
  else {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_save_nothingChanged);
    sendLog(logBuf);
  }
}




void loadConf_defaults()
{
  // set initial deviceName
  createDeviceName();

  // confDevWiFi
  // strlcpy(deviceName, DEVICE_NAME, sizeof(deviceName)); // now done via createDeviceName()
  strlcpy(confDevWiFi.hostName, confDevWiFi.deviceName, sizeof(confDevWiFi.hostName)); // copy deviceName to hostName as initial value
  strlcpy(confSecrets.WiFiAPModePassword, DEFAULT_WIFI_APMODE_PASSWORD, sizeof(confSecrets.WiFiAPModePassword));
  confDevWiFi.WiFiAPModeTimeout = DEFAULT_WIFI_APMODE_TIMEOUT;
  confDevWiFi.WiFiRetryInterval = DEFAULT_WIFI_RETRY_INTERVAL;
  confDevWiFi.WiFiConnCheckInterval = DEFAULT_WIFI_CONNCHECK_INTERVAL;
  confDevWiFi.WiFiRebootOnNoConnect = DEFAULT_WIFI_REBOOT_ONNOCONNECT;
  confDevWiFi_wasChanged = false;

  // confWeb
  strlcpy(confSecrets.http_token, HTTP_SET_TOKEN, sizeof(confSecrets.http_token));
  strlcpy(confSecrets.http_user, DEFAULT_HTTP_USER, sizeof(confSecrets.http_user));
  strlcpy(confSecrets.http_pass, DEFAULT_HTTP_PASS, sizeof(confSecrets.http_pass));
  confWeb.http_user_auth = DEFAULT_HTTP_USER_AUTH;
  confWeb_wasChanged = false;

  // confMqtt
  confMqtt.mqtt_enable = MQTT_ENABLE;
  strlcpy(confMqtt.mqtt_server, MQTT_SERVER, sizeof(confMqtt.mqtt_server));
  confMqtt.mqtt_port = MQTT_PORT;
  strlcpy(confSecrets.mqtt_user, MQTT_USER, sizeof(confSecrets.mqtt_user));
  strlcpy(confSecrets.mqtt_pass, MQTT_PASS, sizeof(confSecrets.mqtt_pass));
  strlcpy(confMqtt.mqtt_topic_in, MQTT_TOPIC_IN, sizeof(confMqtt.mqtt_topic_in));
  strlcpy(confMqtt.mqtt_topic_out, MQTT_TOPIC_OUT, sizeof(confMqtt.mqtt_topic_out));
  strlcpy(confMqtt.mqtt_willTopic, MQTT_WILLTOPIC, sizeof(confMqtt.mqtt_willTopic));
  confMqtt.mqtt_willQos = MQTT_WILLQOS;
  confMqtt.mqtt_willRetain = MQTT_WILLRETAIN;
  strlcpy(confMqtt.mqtt_willMsg, MQTT_WILLMSG, sizeof(confMqtt.mqtt_willMsg));
  strlcpy(confMqtt.mqtt_connMsg, MQTT_CONNMSG, sizeof(confMqtt.mqtt_connMsg));
  confMqtt.mqtt_outRetain = MQTT_OUT_RETAIN;
  confMqtt.mqtt_outRetain_sensors = MQTT_OUT_RETAIN_SENSORS;
  confMqtt.mqtt_enable_heartbeat = MQTT_ENABLE_HEARTBEAT;
  confMqtt.mqtt_heartbeat_maxage_reconnect = MQTT_HEARTBEAT_MAXAGE;
  confMqtt.mqtt_heartbeat_maxage_reboot = MQTT_HEARTBEAT_MAXAGE_REBOOT;
  confMqtt_wasChanged = false;

  // confAdd
  strlcpy(confAdd.mqtt_topic_pir, MQTT_TOPIC_PIR, sizeof(confAdd.mqtt_topic_pir));
  strlcpy(confAdd.mqtt_payload_pir_on, MQTT_TOPIC_PIR_ON, sizeof(confAdd.mqtt_payload_pir_on));
  strlcpy(confAdd.mqtt_payload_pir_off, MQTT_TOPIC_PIR_OFF, sizeof(confAdd.mqtt_payload_pir_off));
  strlcpy(confAdd.outTemp_topic_in, OUTTEMP_TOPIC_IN, sizeof(confAdd.outTemp_topic_in));
  strlcpy(confAdd.outHum_topic_in, OUTHUM_TOPIC_IN, sizeof(confAdd.outHum_topic_in));
  confAdd_wasChanged = false;

  // confTime
  #ifdef ENABLE_FEATURE_NTP_TIME
  confTime.ntpEnable = DEFAULT_NTP_ENABLED;
  strlcpy(confTime.timeZoneStr, DEFAULT_TIMEZONE, sizeof(confTime.timeZoneStr));
  strlcpy(confTime.ntpServer1, DEFAULT_NTP_SERVER, sizeof(confTime.ntpServer1));
  confTime.ntpSyncInterval = DEFAULT_NTP_SYNC_INTERVAL;
  confTime_wasChanged = false;
  #endif

  // confLog
  confLog.logLevelSerial = DEFAULT_LOGLEVEL_SERIAL;
  confLog.logLevelWeb = DEFAULT_LOGLEVEL_WEB;
  confLog.logLevelMqtt = DEFAULT_LOGLEVEL_MQTT;
  confLog.logLevelSyslog = DEFAULT_LOGLEVEL_SYSLOG;
  confLog_wasChanged = false;

  // confSens
  confSens.measureInterval = DEFAULT_MEASURE_INTERVAL;

  // confDisplay
  confDisplay.displayInterval = DEFAULT_DISPLAY_INTERVAL;
  confDisplay.displayTimeout = DEFAULT_DISPLAY_TIMEOUT;
  confDisplay.PIRenablesDisplay = DEFAULT_PIR_ENABLES_DISPLAY;

  #ifdef FIRMWARE_VARIANT_THERMOSTAT
  // confBas
  confTherm.setTempMin = DEFAULT_SETTEMP_MIN;
  confTherm.setTempMax = DEFAULT_SETTEMP_MAX;
  confTherm.autoSaveSetTemp = AUTOSAVE_SETTEMP;
  confTherm.autoSaveHeatingMode = AUTOSAVE_SETMODE;
  confTherm.saveToMqttRetained = SAVE_TO_MQTT_RETAINED;
  confTherm.PIRenablesDisplay_preset0only = DEFAULT_PIR_ENABLES_DISPLAY_PRESET0_ONLY;
  confTherm.togglingTempHumAIDisplay = DEFAULT_TOGGLING_I_O_TEMPHUM;
  confTherm.hysteresis = DEFAULT_HYSTERESIS;
  confTherm.heatingMinOffTime = DEFAULT_HEATING_MIN_OFFTIME;
  confTherm.setTempDecreaseVal = SETTEMP_DECREASE_VALUE;
  strlcpy(confTherm.offMessage, OFF_MESSAGE, sizeof(confTherm.offMessage));
  strlcpy(confTherm.iTempLabel, INSIDE_TEMP_LABEL, sizeof(confTherm.iTempLabel));
  strlcpy(confTherm.oTempLabel, OUTSIDE_TEMP_LABEL, sizeof(confTherm.oTempLabel));
  strlcpy(confTherm.modeName0, MODE_NAME_0, sizeof(confTherm.modeName0));
  strlcpy(confTherm.modeName1, MODE_NAME_1, sizeof(confTherm.modeName1));
  strlcpy(confTherm.psetName0, PRESET_NAME_0, sizeof(confTherm.psetName0));
  strlcpy(confTherm.psetName1, PRESET_NAME_1, sizeof(confTherm.psetName1));
  strlcpy(confTherm.psetName2, PRESET_NAME_2, sizeof(confTherm.psetName2));
  confTherm.pauseTout = 1800;
  confTherm_wasChanged = false;
  #endif

}

void loadConf_restoreDefaultWhenMissing()
{
  if (strlen(confDevWiFi.deviceName) < 4)
    createDeviceName();

  if (strlen(confDevWiFi.hostName) < 4)
    strlcpy(confDevWiFi.hostName, confDevWiFi.deviceName, sizeof(confDevWiFi.hostName));


  #ifdef FIRMWARE_VARIANT_THERMOSTAT
  if (confTherm.modeName0[0] == '\0')
    strlcpy(confTherm.modeName0, MODE_NAME_0, sizeof(confTherm.modeName0));
  if (confTherm.modeName1[0] == '\0')
    strlcpy(confTherm.modeName1, MODE_NAME_1, sizeof(confTherm.modeName1));
  if (confTherm.psetName0[0] == '\0')
    strlcpy(confTherm.psetName0, PRESET_NAME_0, sizeof(confTherm.psetName0));
  if (confTherm.psetName1[0] == '\0')
    strlcpy(confTherm.psetName1, PRESET_NAME_1, sizeof(confTherm.psetName1));
  if (confTherm.psetName2[0] == '\0')
    strlcpy(confTherm.psetName2, PRESET_NAME_2, sizeof(confTherm.psetName2));
  if (confTherm.iTempLabel[0] == '\0')
    strlcpy(confTherm.iTempLabel, INSIDE_TEMP_LABEL, sizeof(confTherm.iTempLabel));
  if (confTherm.oTempLabel[0] == '\0')
    strlcpy(confTherm.oTempLabel, OUTSIDE_TEMP_LABEL, sizeof(confTherm.oTempLabel));
  #endif

  //confTherm.tempCorrVal = TEMPSENSOR_CORRECTION_VALUE;
  //confTherm.humCorrVal = HUMSENSOR_CORRECTION_VALUE;


  if (confDevWiFi.WiFiConnCheckInterval == 0)
    confDevWiFi.WiFiConnCheckInterval = DEFAULT_WIFI_CONNCHECK_INTERVAL;

  //NTP
  #ifdef ENABLE_FEATURE_NTP_TIME
  if (confTime.ntpEnable && strlen(confTime.ntpServer1) == 0)
    strlcpy(confTime.ntpServer1, DEFAULT_NTP_SERVER, sizeof(confTime.ntpServer1));
  if (confTime.ntpEnable && strlen(confTime.timeZoneStr) == 0)
    strlcpy(confTime.timeZoneStr, DEFAULT_TIMEZONE, sizeof(confTime.timeZoneStr));
  #endif
}



void conf_clearSecrets() {
  #ifdef STORE_SECRETS_IN_EEPROM
    clearSecrets_EEPROM();
  #else
    confClearCredentials();
    confClearWiFiCredentials();
  #endif
}



void confClearCredentials()
{
  strcpy(confSecrets.http_token, "");
  strcpy(confSecrets.http_pass, "");
  strcpy(confSecrets.http_pass1, "");
  strcpy(confSecrets.http_pass2, "");
  strcpy(confSecrets.mqtt_pass, "");
  //saveConf_Web();
  //saveConf_Mqtt();
  saveConf_Secrets();

  snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_clearedCreds);
  sendLog(logBuf);
}



void confClearWiFiCredentials()
{
  strcpy(confSecrets.WiFiPW1, "");
  strcpy(confSecrets.WiFiPW2, "");
  strcpy(confSecrets.WiFiAPModePassword, "");
  //saveConf_DevWiFi();
  saveConf_Secrets();
  snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_clearedWifiCreds);
  sendLog(logBuf);
}


#ifdef ENABLE_FEATURE_SECRETS_ENCRYPTION

bool confCheckEncrypted()
{   
  #ifdef STORE_SECRETS_IN_EEPROM
    uint8_t _data;
    EEPROM.begin(EEPROM_SIZE);
    _data = EEPROM.read(EEPROM_ADDR_SECRETS_ENCRYPTED);
    EEPROM.end();
    if(_data == 1) confEncryptionEnabled = true;
    else confEncryptionEnabled = false;
  #else
    if (LittleFS.exists("/isEncrypted"))
    {
      confEncryptionEnabled = true;
    }
    else
    {
      confEncryptionEnabled = false;
    }
  #endif
  if(confEncryptionEnabled) {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_secretsEncrypted);
    sendLog(logBuf);
    return true;
  }
  else {
    if(debug > 0) { 
      snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_secretsNotEncrypted);
      sendLog(logBuf);
    }
    return false;
  }
}


void confEncrypt(){
  confEncrypt(false);
}
void confEncrypt(bool _force)
{
  if (!confCheckEncrypted() || _force)
  {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_encryptingSecrets);
    sendLog(logBuf);
    confEncryptionEnabled = true;
    
    saveConf_Secrets(true);

    #ifdef STORE_SECRETS_IN_EEPROM
      EEPROM.begin(EEPROM_SIZE);
      EEPROM.write(EEPROM_ADDR_SECRETS_ENCRYPTED, 1);
      EEPROM.commit();
      EEPROM.end();
    #else
      File configFile = LittleFS.open("/isEncrypted", "w");
      configFile.close();
    #endif
    
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_encryptingSecretsDone);
    sendLog(logBuf);
  }
  else
  {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_alreadyEncrypted);
    sendLog(logBuf);
  }
}



void confEncryptOff()
{
  if (confCheckEncrypted())
  {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_encryptionOff);
    sendLog(logBuf);
    confEncryptionEnabled = false;
    //confClearCredentials();
    //confClearWiFiCredentials();
    conf_clearSecrets();

    #ifdef STORE_SECRETS_IN_EEPROM
      EEPROM.begin(EEPROM_SIZE);
      EEPROM.write(EEPROM_ADDR_SECRETS_ENCRYPTED, 0);
      EEPROM.commit();
      EEPROM.end();
    #else
      LittleFS.remove("/isEncrypted");
    #endif

    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_encryptionOffDone);
    sendLog(logBuf);
  }
  else
  {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_secretsNotEncrypted);
    sendLog(logBuf);
  }
}

#endif

bool confCheckUnsaved()
{
  bool confChanged = false;
  if (confSecrets_wasChanged) confChanged = true;
  if (confDevWiFi_wasChanged) confChanged = true;
  if (confWeb_wasChanged) confChanged = true;
  if (confMqtt_wasChanged) confChanged = true;
  if (confAdd_wasChanged) confChanged = true;
  if (confTime_wasChanged) confChanged = true;
  if (confLog_wasChanged) confChanged = true;
  if (confSens_wasChanged) confChanged = true;

  #ifdef FIRMWARE_VARIANT_THERMOSTAT
  if (confTherm_wasChanged) confChanged = true;
  #endif

  return confChanged;
}



void conf_confChangedLogNote(bool force = false)
{
  if (confCheckUnsaved() && (force || (!lastConfigChangeNoteAlreadyDone && (millis() - lastConfigChange) > 5000)))
  {
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_pendingConfChanges);
    sendLog(logBuf);
    confMqttConnResetRequiredLogNote();
    confRestartRequiredLogNote();
    lastConfigChangeNoteAlreadyDone = true;
  }
  if(force) {
    confMqttConnResetRequiredLogNote();
    confRestartRequiredLogNote();
  }
}



void confRestartRequiredLogNote()
{
  if (configChangedRestartRequired)
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_restartRequired);
    sendLog(logBuf);
}



void confMqttConnResetRequiredLogNote()
{
  if (configChangedMqttConnResetRequired)
    snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_conf_mqttReconnectRequired);
    sendLog(logBuf);
}
