
bool setConfig(char* param, char* value) {
  // sets the corresponding config variable for 'param' to new value
  // does not trigger saving to flash
  // does not distinguish between config and config2 as this is only split on flash and web-interface

  if (debug) {
    Serial.print("setConfig - '");
    Serial.print(param);
    Serial.print("' to '");
    Serial.print(value);
    Serial.println("'");
  }

  // values
  if ( strcmp(param, "temp") == 0 ) {
    float valueFloat = round(atof(value) * 2.0) / 2.0;
#ifdef DEBUG_VERBOSE
    Serial.print(valueFloat);
#endif
    setTempTo(valueFloat);
  }
  else if ( strcmp(param, "tempLow") == 0 ) {
    float valueFloat = round(atof(value) * 2.0) / 2.0;
#ifdef DEBUG_VERBOSE
    Serial.print(valueFloat);
#endif
    setTempLowTo(valueFloat);
  }
  else if ( strcmp(param, "mode") == 0 ) {
    setHeatingmodeTo(atoi(value));
  }

  //confdata
  else if ( strcmp(param, "devName") == 0 ) {
    strlcpy(deviceName, value, 31);
  }
  else if ( strcmp(param, "httpUser") == 0 ) {
    strlcpy(http_user, value, 31);
  }
  else if ( strcmp(param, "httpPass") == 0 ) {
    strlcpy(http_pass, value, 31);
  }
  else if ( strcmp(param, "mqttHost") == 0 ) {
    strlcpy(mqtt_server, value, 41);
  }
  else if ( strcmp(param, "mqttPort") == 0 ) {
    mqtt_port = atoi(value);
  }
  else if ( strcmp(param, "mqttUser") == 0 ) {
    strlcpy(mqtt_user, value, 31);
  }
  else if ( strcmp(param, "mqttPass") == 0 ) {
    strlcpy(mqtt_pass, value, 31);
  }
  else if ( strcmp(param, "inTop") == 0 ) {
    strlcpy(mqtt_topic_in, value, 51);
  }
  else if ( strcmp(param, "outTop") == 0 ) {
    strlcpy(mqtt_topic_out, value, 51);
  }
  else if ( strcmp(param, "outRet") == 0 ) {
    if (atoi(value) == 1) mqtt_outRetain = true;
    else mqtt_outRetain = false;
  }
  else if ( strcmp(param, "willTop") == 0 ) {
    strlcpy(mqtt_willTopic, value, 51);
  }
  else if ( strcmp(param, "willQos") == 0 ) {
    int tmpval = atoi(value);
    if (tmpval >= 0 && tmpval <= 2) mqtt_willQos = tmpval;
  }
  else if ( strcmp(param, "willRet") == 0 ) {
    if (atoi(value) == 1) mqtt_willRetain = true;
    else mqtt_willRetain = false;
  }
  else if ( strcmp(param, "willMsg") == 0 ) {
    strlcpy(mqtt_willMsg, value, 31);
  }
  else if ( strcmp(param, "domOutTop") == 0 ) {
    strlcpy(domoticz_out_topic, value, 51);
  }

  //confdata2
  else if ( strcmp(param, "domIdxTherm") == 0 ) {
    domoticzIdx_Thermostat = atoi(value);
  }
  else if ( strcmp(param, "domIdxMode") == 0 ) {
    domoticzIdx_ThermostatMode = atoi(value);
  }
  else if ( strcmp(param, "domIdxTempHum") == 0 ) {
    domoticzIdx_TempHumSensor = atoi(value);
  }
  else if ( strcmp(param, "domIdxPIR") == 0 ) {
    domoticzIdx_PIR = atoi(value);
  }
  else if ( strcmp(param, "outTempTop") == 0 ) {
    strlcpy(outTemp_topic_in, value, 51);
  }
  else if ( strcmp(param, "outHumTop") == 0 ) {
    strlcpy(outHum_topic_in, value, 51);
  }
  else if ( strcmp(param, "autoSaveTemp") == 0 ) {
    if (atoi(value) == 1) autoSaveSetTemp = true;
    else autoSaveSetTemp = false;
  }
  else if ( strcmp(param, "autoSaveMode") == 0 ) {
    if (atoi(value) == 1) autoSaveHeatingMode = true;
    else autoSaveHeatingMode = false;
  }
  else if ( strcmp(param, "minOffTime") == 0 ) {
    heatingMinOffTime = atoi(value);
  }
  else if ( strcmp(param, "tempMin") == 0 ) {
    float valueFloat = round(atof(value) * 2.0) / 2.0;
#ifdef DEBUG_VERBOSE
    Serial.print(valueFloat);
#endif
    if (valueFloat >= 10 && valueFloat <= 16) {
      setTempMin = valueFloat;
    }
  }
  else if ( strcmp(param, "tempMax") == 0 ) {
    float valueFloat = round(atof(value) * 2.0) / 2.0;
#ifdef DEBUG_VERBOSE
    Serial.print(valueFloat);
#endif
    if (valueFloat >= 18 && valueFloat <= 30) {
      setTempMax = valueFloat;
    }
  }
  else if ( strcmp(param, "hyst") == 0 ) {
    float valueFloat = atof(value);
#ifdef DEBUG_VERBOSE
    Serial.print(valueFloat);
#endif
    if (valueFloat >= 0.1 && valueFloat <= 4.0) {
      hysteresis = valueFloat;
    }
  }
  else if ( strcmp(param, "tempCorr") == 0 ) {
    float valueFloat = atof(value);
    if (valueFloat >= -5.0 && valueFloat <= 5.0) {
      tempCorrVal = valueFloat;
    }
  }
  else if ( strcmp(param, "humCorr") == 0 ) {
    int valueInt = atoi(value);
    if (valueInt >= -40 && valueInt <= 40) {
      humCorrVal = valueInt;
    }
  }
  else if ( strcmp(param, "measInt") == 0 ) {
    int valueInt = atoi(value);
    if (valueInt >= 5 && valueInt <= 120) {
      measureInterval = valueInt;
    }
  }
  else if ( strcmp(param, "dispInt") == 0 ) {
    int valueInt = atoi(value);
    if (valueInt >= 2 && valueInt <= 120) {
      displayInterval = valueInt;
    }
  }
  else if ( strcmp(param, "dispTout") == 0 ) {
    int valueInt = atoi(value);
    if (valueInt >= 2 && valueInt <= 1200) {
      displayTimeout = valueInt;
    }
  }
}

void getConfig(char* param) {
  // gets and prints the corresponding config variable for 'param'

  if (debug) {
    Serial.print("getConfig - '");
    Serial.print(param);
    Serial.println("'");
  }

  char buf[101];

  // values
  if ( strcmp(param, "temp") == 0 ) {
    char buf2[11];
    dtostrf(setTemp, 2, 1, buf2);
    sprintf(buf, "setTemp: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "tempLow") == 0 ) {
    char buf2[11];
    dtostrf(setTempLow, 2, 1, buf2);
    sprintf(buf, "setTempLow: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "mode") == 0 ) {
    sprintf(buf, "heatingMode: '%d'", heatingMode);
    sendStatus(buf);
  }

  //confdata
  else if ( strcmp(param, "devName") == 0 ) {
    sprintf(buf, "devName: '%s'", deviceName);
    sendStatus(buf);
  }
  else if ( strcmp(param, "httpUser") == 0 ) {
    sprintf(buf, "httpUser: '%s'", http_user);
    sendStatus(buf);
  }
  else if ( strcmp(param, "httpPass") == 0 ) {
    sprintf(buf, "httpPass: '%s'", http_pass);
    sendStatus(buf);
  }
  else if ( strcmp(param, "mqttHost") == 0 ) {
    sprintf(buf, "mqttHost: '%s'", mqtt_server);
    sendStatus(buf);
  }
  else if ( strcmp(param, "mqttPort") == 0 ) {
    sprintf(buf, "mqttPort: '%s'", mqtt_port);
    sendStatus(buf);
  }
  else if ( strcmp(param, "mqttUser") == 0 ) {
    sprintf(buf, "mqttUser: '%s'", mqtt_user);
    sendStatus(buf);
  }
  else if ( strcmp(param, "mqttPass") == 0 ) {
    sprintf(buf, "mqttPass: '%s'", mqtt_pass);
    sendStatus(buf);
  }
  else if ( strcmp(param, "inTop") == 0 ) {
    sprintf(buf, "inTop: '%s'", mqtt_topic_in);
    sendStatus(buf);
  }
  else if ( strcmp(param, "outTop") == 0 ) {
    sprintf(buf, "outTop: '%s'", mqtt_topic_out);
    sendStatus(buf);
  }
  else if ( strcmp(param, "outRet") == 0 ) {
    char buf2[11];
    if (mqtt_outRetain) strcpy(buf2, "1");
    else strcpy(buf2, "0");
    sprintf(buf, "outRet: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "willTop") == 0 ) {
    sprintf(buf, "willTop: '%s'", mqtt_willTopic);
    sendStatus(buf);
  }
  else if ( strcmp(param, "willQos") == 0 ) {
    sprintf(buf, "willQos: '%d'", mqtt_willQos);
    sendStatus(buf);
  }
  else if ( strcmp(param, "willRet") == 0 ) {
    char buf2[11];
    if (mqtt_willRetain) strcpy(buf2, "1");
    else strcpy(buf2, "0");
    sprintf(buf, "willRet: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "willMsg") == 0 ) {
    sprintf(buf, "willMsg: '%s'", mqtt_willMsg);
    sendStatus(buf);
  }
  else if ( strcmp(param, "domOutTop") == 0 ) {
    sprintf(buf, "domOutTop: '%s'", domoticz_out_topic);
    sendStatus(buf);
  }

  //confdata2
  else if ( strcmp(param, "domIdxTherm") == 0 ) {
    sprintf(buf, "domIdxTherm: '%d'", domoticzIdx_Thermostat);
    sendStatus(buf);
  }
  else if ( strcmp(param, "domIdxMode") == 0 ) {
    sprintf(buf, "domIdxMode: '%d'", domoticzIdx_ThermostatMode);
    sendStatus(buf);
  }
  else if ( strcmp(param, "domIdxTempHum") == 0 ) {
    sprintf(buf, "domIdxTempHum: '%d'", domoticzIdx_TempHumSensor);
    sendStatus(buf);
  }
  else if ( strcmp(param, "domIdxPIR") == 0 ) {
    sprintf(buf, "domIdxPIR: '%d'", domoticzIdx_PIR);
    sendStatus(buf);
  }
  else if ( strcmp(param, "outTempTop") == 0 ) {
    sprintf(buf, "outTempTop: '%s'", outTemp_topic_in);
    sendStatus(buf);
  }
  else if ( strcmp(param, "outHumTop") == 0 ) {
    sprintf(buf, "outHumTop: '%s'", outHum_topic_in);
    sendStatus(buf);
  }
  else if ( strcmp(param, "autoSaveTemp") == 0 ) {
    char buf2[11];
    if (autoSaveSetTemp) strcpy(buf2, "1");
    else strcpy(buf2, "0");
    sprintf(buf, "autoSaveTemp: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "autoSaveMode") == 0 ) {
    char buf2[11];
    if (autoSaveHeatingMode) strcpy(buf2, "1");
    else strcpy(buf2, "0");
    sprintf(buf, "autoSaveMode: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "minOffTime") == 0 ) {
    sprintf(buf, "minOffTime: '%d'", heatingMinOffTime);
    sendStatus(buf);
  }
  else if ( strcmp(param, "tempMin") == 0 ) {
    char buf2[11];
    dtostrf(setTempMin, 2, 1, buf2);
    sprintf(buf, "tempMin: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "tempMax") == 0 ) {
    char buf2[11];
    dtostrf(setTempMax, 2, 1, buf2);
    sprintf(buf, "tempMax: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "hyst") == 0 ) {
    char buf2[11];
    dtostrf(hysteresis, 2, 1, buf2);
    sprintf(buf, "hyst: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "tempCorr") == 0 ) {
    char buf2[11];
    dtostrf(tempCorrVal, 2, 1, buf2);
    sprintf(buf, "tempCorr: '%s'", buf2);
    sendStatus(buf);
  }
  else if ( strcmp(param, "humCorr") == 0 ) {
    sprintf(buf, "humCorr: '%d'", humCorrVal);
    sendStatus(buf);
  }
  else if ( strcmp(param, "measInt") == 0 ) {
    sprintf(buf, "measInt: '%d'", measureInterval);
    sendStatus(buf);
  }
  else if ( strcmp(param, "dispInt") == 0 ) {
    sprintf(buf, "dispInt: '%d'", displayInterval);
    sendStatus(buf);
  }
  else if ( strcmp(param, "dispTout") == 0 ) {
    sprintf(buf, "dispTout: '%d'", displayTimeout);
    sendStatus(buf);
  }
}

void printConfig() {
  // prints current config vars to serial
  Serial.println("\nconfdata:");
  Serial.print("devName: ");
  Serial.println(deviceName);
  Serial.print("httpUser: ");
  Serial.println(http_user);
  Serial.print("httpPass: ");
  Serial.println(http_pass);
  Serial.print("mqttHost: ");
  Serial.println(mqtt_server);
  Serial.print("mqttPort: ");
  Serial.println(mqtt_port);
  Serial.print("mqttUser: ");
  Serial.println(mqtt_user);
  Serial.print("mqttPass: ");
  Serial.println(mqtt_pass);
  Serial.print("inTop: ");
  Serial.println(mqtt_topic_in);
  Serial.print("outTop: ");
  Serial.println(mqtt_topic_out);
  Serial.print("outRet: ");
  Serial.println(mqtt_outRetain);
  Serial.print("willTop: ");
  Serial.println(mqtt_willTopic);
  Serial.print("willQos: ");
  Serial.println(mqtt_willQos);
  Serial.print("willRet: ");
  Serial.println(mqtt_willRetain);
  Serial.print("willMsg: ");
  Serial.println(mqtt_willMsg);
  Serial.print("domOutTop: ");
  Serial.println(domoticz_out_topic);
  Serial.println();
}
void printConfig2() {
  Serial.println("\nconfdata2:");
  Serial.print("domIdxTherm: ");
  Serial.println(domoticzIdx_Thermostat);
  Serial.print("domIdxMode: ");
  Serial.println(domoticzIdx_ThermostatMode);
  Serial.print("domIdxTempHum: ");
  Serial.println(domoticzIdx_TempHumSensor);
  Serial.print("domIdxPIR: ");
  Serial.println(domoticzIdx_PIR);
  Serial.print("outTempTop: ");
  Serial.println(outTemp_topic_in);
  Serial.print("outHumTop: ");
  Serial.println(outHum_topic_in);
  Serial.print("autoSaveTemp: ");
  Serial.println(autoSaveSetTemp);
  Serial.print("autoSaveMode: ");
  Serial.println(autoSaveHeatingMode);
  Serial.print("minOffTime: ");
  Serial.println(heatingMinOffTime);
  Serial.print("tempMin: ");
  Serial.println(setTempMin);
  Serial.print("tempMax: ");
  Serial.println(setTempMax);
  Serial.print("hyst: ");
  Serial.println(hysteresis);
  Serial.print("tempCorr: ");
  Serial.println(tempCorrVal);
  Serial.print("humCorr: ");
  Serial.println(humCorrVal);
  Serial.print("measInt: ");
  Serial.println(measureInterval);
  Serial.print("dispInt: ");
  Serial.println(displayInterval);
  Serial.print("dispTout: ");
  Serial.println(displayTimeout);
  Serial.println();
}


bool loadConfig() { // loadConfig 1
  if (SPIFFS.exists("/conf.json")) {
    File configFile = SPIFFS.open("/conf.json", "r");
    if (!configFile) {
      Serial.println("ERR: Failed to open file /conf.json");
      return false;
    }
    else {
      Serial.println("file /conf.json opened");
      size_t size = configFile.size();

      Serial.print("file size: ");
      Serial.println(size);

      //      Serial.println("file content:");
      //
      //      while (configFile.available()) {
      //        //Lets read line by line from the file
      //        String line = configFile.readStringUntil('\n');
      //        Serial.println(line);
      //      }
      //      Serial.println();

      if (size > 1000) {
        Serial.println("Config file size is too large");
        return false;
      }

      Serial.println("allocate buffer");
      // Allocate a buffer to store contents of the file.
      std::unique_ptr<char[]> buf(new char[size]);

      Serial.println("read file bytes to buffer");
      // We don't use String here because ArduinoJson library requires the input
      // buffer to be mutable. If you don't use ArduinoJson, you may as well
      // use configFile.readString instead.
      configFile.readBytes(buf.get(), size);

      StaticJsonBuffer<1050> jsonBuffer;
      JsonObject& json = jsonBuffer.parseObject(buf.get());

      if (!json.success()) {
        Serial.println("Failed to parse config file");
        return false;
      }

      strlcpy(deviceName, json["devName"] | "", 31);
      strlcpy(http_user, json["httpUser"] | "", 31);
      strlcpy(http_pass, json["httpPass"] | "", 31);
      strlcpy(mqtt_server, json["mqttHost"] | "", 41);
      mqtt_port = atoi(json["mqttPort"] | "");
      strlcpy(mqtt_user, json["mqttUser"] | "", 31);
      strlcpy(mqtt_pass, json["mqttPass"] | "", 31);
      strlcpy(mqtt_topic_in, json["inTop"] | "", 51);
      strlcpy(mqtt_topic_out, json["outTop"] | "", 51);

      if (atoi(json["outRet"] | "") == 1) mqtt_outRetain = true;
      else mqtt_outRetain = false;

      strlcpy(mqtt_willTopic, json["willTop"] | "", 51);
      mqtt_willQos = atoi(json["willQos"] | "0");

      if (atoi(json["willRet"] | "") == 1) mqtt_willRetain = true;
      else mqtt_willRetain = false;

      strlcpy(mqtt_willMsg, json["willMsg"] | "", 31);
      strlcpy(domoticz_out_topic, json["domOutTop"] | "", 51);

      Serial.println("Loaded config values:");
      printConfig();
      return true;
    }
    configFile.close();
  }
  else {
    Serial.println("file /config.json file does not exist");
    return false;
  }


} // loadConfig 1

bool loadConfig2() {
  if (SPIFFS.exists("/conf2.json")) {
    File configFile = SPIFFS.open("/conf2.json", "r");
    if (!configFile) {
      Serial.println("ERR: Failed to open file /conf2.json");
      return false;
    }
    else {
      Serial.println("file /conf2.json opened");
      size_t size = configFile.size();
      Serial.print("file size: ");
      Serial.println(size);
      if (size > 1000) {
        Serial.println("Config file size is too large");
        return false;
      }

      // Allocate a buffer to store contents of the file.
      std::unique_ptr<char[]> buf(new char[size]);

      // We don't use String here because ArduinoJson library requires the input
      // buffer to be mutable. If you don't use ArduinoJson, you may as well
      // use configFile.readString instead.
      configFile.readBytes(buf.get(), size);

      StaticJsonBuffer<1050> jsonBuffer;
      JsonObject& json = jsonBuffer.parseObject(buf.get());

      if (!json.success()) {
        Serial.println("Failed to parse config file");
        return false;
      }

      domoticzIdx_Thermostat = atoi(json["domIdxTherm"] | "");
      domoticzIdx_ThermostatMode = atoi(json["domIdxMode"] | "");
      domoticzIdx_TempHumSensor = atoi(json["domIdxTempHum"] | "");
      domoticzIdx_PIR = atoi(json["domIdxPIR"] | "");

      Serial.println("Loaded config values:");
      printConfig2();
      return true;
    }
  }
  else {
    Serial.println("file /conf2.json file does not exist");
    return false;
  }
} //loadConfig2


bool loadSetTemp() { // loadSetTemp
  File configFile = SPIFFS.open("/setTemp", "r");
  if (!configFile) {
    Serial.println("ERR: Failed to open file /setTemp");
    return false;
  }
  String s = configFile.readStringUntil('\n');
  configFile.close();
  float tmpSetTemp = s.toFloat();
  if ( tmpSetTemp >= setTempMin && tmpSetTemp <= setTempMax ) {
    setTemp = tmpSetTemp;
    return true;
  }
  else return false;
} // loadSetTemp


bool loadHeatingMode() { // loadHeatingMode
  File configFile = SPIFFS.open("/heatingMode", "r");
  if (!configFile) {
    Serial.println("ERR: Failed to open file /heatingMode");
    return false;
  }
  String s = configFile.readStringUntil('\n');
  configFile.close();
  int tmpHeatingMode = s.toInt();
  if ( tmpHeatingMode >= 0 && tmpHeatingMode <= 2 ) {
    heatingMode = tmpHeatingMode;
    return true;
  }
  else return false;
} // loadHeatingMode


bool saveConfig() { // safeConfig
  StaticJsonBuffer<1050> jsonBuffer;
  JsonObject& json = jsonBuffer.createObject();

  json["devName"] = deviceName;
  json["httpUser"] = http_user;
  json["httpPass"] = http_pass;
  json["mqttHost"] = mqtt_server;
  json["mqttPort"] = mqtt_port;
  json["mqttUser"] = mqtt_user;
  json["mqttPass"] = mqtt_pass;
  json["inTop"] = mqtt_topic_in;
  json["outTop"] = mqtt_topic_out;
  json["outRet"] = mqtt_outRetain;
  json["willTop"] = mqtt_willTopic;
  json["willQos"] = mqtt_willQos;
  json["willRet"] = mqtt_willRetain;
  json["willMsg"] = mqtt_willMsg;
  json["domOutTop"] = domoticz_out_topic;

  yield();

  File configFile = SPIFFS.open("/conf.json", "w");
  if (!configFile) {
    Serial.println("Failed to open conf file for writing");
    return false;
  }

  json.printTo(configFile);
  configFile.close();
  return true;
} // safeConfig


bool saveConfig2() { // safeConfig2
  StaticJsonBuffer<1050> jsonBuffer;
  JsonObject& json = jsonBuffer.createObject();

  json["domIdxTherm"] = domoticzIdx_Thermostat;
  json["domIdxMode"] = domoticzIdx_ThermostatMode;
  json["domIdxTempHum"] = domoticzIdx_TempHumSensor;
  json["domIdxPIR"] = domoticzIdx_PIR;

  yield();

  File configFile = SPIFFS.open("/conf2.json", "w");
  if (!configFile) {
    Serial.println("Failed to open conf2 file for writing");
    return false;
  }

  json.printTo(configFile);
  configFile.close();
  return true;
} // safeConfig2


bool saveSetTemp() { // saveSetTemp
  File configFile = SPIFFS.open("/setTemp", "w");
  if (!configFile) {
    Serial.println("Failed to open setTemp file for writing");
    return false;
  }
  configFile.println(setTemp);
  configFile.close();
  setTempSaved = setTemp;
  return true;
} // saveSetTemp

bool saveHeatingMode() { // saveHeatingMode
  File configFile = SPIFFS.open("/heatingMode", "w");
  if (!configFile) {
    Serial.println("Failed to open heatingMode file for writing");
    return false;
  }
  configFile.println(heatingMode);
  configFile.close();
  heatingModeSaved = heatingMode;
  return true;
} // saveHeatingMode


void checkSaveConfigTriggered() {
  if (saveConfigToFlash) {
    saveConfigToFlash = false;
    saveConfig();
  }
  if (saveConfig2ToFlash) {
    saveConfig2ToFlash = false;
    saveConfig2();
  }
  //  if (saveSetTempToFlash) {
  //    saveSetTempToFlash = false;
  //    saveSetTemp();
  //  }
  //  if (saveHeatingModeToFlash) {
  //    saveHeatingModeToFlash = false;
  //    saveHeatingMode();
  //  }

}

void deleteConfig() {
  Serial.println("deleting configuration");
  if (SPIFFS.remove("/formatComplete.txt")) {
    Serial.println("config will be deleted after reboot");
    delay(100);
    ESP.restart();
  }
}


