
#define SER_INPUT_SIZE 70
char serBuffer[SER_INPUT_SIZE + 1];
int serBufferCount;

void serialEvent()
{
  char ch = Serial.read();
  serBuffer[serBufferCount] = ch;
  serBufferCount++;
  if (ch == 13 || ch == 10)
  { // ASCII code 13 = "CR",  10 = "LF"
    serBuffer[serBufferCount - 1] = '\0';
    #ifdef DEBUG_VERBOSE
      Serial.print(F("serial cmd: '"));
      Serial.print(serBuffer);
      Serial.println("'");
    #endif
    strlcpy(cmdPayload, serBuffer, sizeof(cmdPayload));
    cmdInQueue = true;
    evalCmd();
    serBufferCount = 0;
  }
}

void evalCmd()
{
  if (cmdInQueue)
  {
    //Serial.print("cmdPayload: ");
    //Serial.println(cmdPayload);

    char cmdPayload_lower[sizeof(cmdPayload)];
    strlcpy(cmdPayload_lower, cmdPayload, sizeof(cmdPayload_lower));
    strlwr(cmdPayload_lower);

    if (strncmp(cmdPayload_lower, "loadconf", 8) == 0)
    {
      sprintf_P(logBuf, PGMStr_conf_loading);
      sendLog(logBuf);
      loadConf_all();
    }

    else if (strncmp(cmdPayload_lower, "set ", 4) == 0)
    {
      char buf[81];
      char setconfCmd[16];

      uint8_t len = strlen(cmdPayload) - 4;
      for (unsigned char i = 0; i < len; i++)
      {
        if (i < (sizeof(buf) - 1))
          buf[i] = cmdPayload[i + 4];
      }
      if (len <= (sizeof(buf) - 1))
        buf[len] = '\0';
      else
        buf[(sizeof(buf) - 1)] = '\0';

      #ifdef DEBUG_VERBOSE
        Serial.print(F("Buf: "));
        Serial.println(buf);
      #endif

      bool cmdNoPayload = false;
      uint8_t setconfCmdLen = 0;
      for (unsigned char i = 0; i < len; i++)
      {
        //if (buf[i] == 32 || buf[i] == '\0') break; // if SPACE command name is finished, if \0 command parameter is missing
        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58)
          break; // if SPACE(32) or =(61) or :(58) command name is finished
        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13)
        { // if \0, LF (10) or CR (13) command parameter is missing
          cmdNoPayload = true;
          break;
        }
        setconfCmd[i] = buf[i];
        setconfCmdLen++;
      }
      setconfCmd[setconfCmdLen] = '\0';
      yield();

      if (setconfCmdLen == len)
        cmdNoPayload = true;

#ifdef DEBUG_VERBOSE
      Serial.print(F("setconfCmd: '"));
      Serial.print(setconfCmd);
      Serial.print("'");
#endif

      if (cmdNoPayload)
      {
        #ifdef DEBUG_VERBOSE
          Serial.println(F(", no payload, displaying current value"));
        #endif
        //getConfig(setconfCmd);
        cmdPrintHelp();
      }
      else
      {
        char setconfPayload[62];
        #ifdef DEBUG_VERBOSE
          Serial.println();
        #endif

        int setconfPayloadLen = 0;
        for (int i = 0; i < len; i++)
        {
          char c = buf[i + setconfCmdLen + 1];
          if (c == 0 || c == 10 || c == 13)
            break; // if \0, LF (10) or CR (13) command parameter is finished
          setconfPayload[i] = c;
          setconfPayloadLen++;
        }
        setconfPayload[setconfPayloadLen] = '\0';

        #ifdef DEBUG_VERBOSE
          Serial.print(F("setconfPayload: '"));
          Serial.print(setconfPayload);
          Serial.println("'");
        #endif

        snprintf(logBuf, LOG_BUFFER_SIZE, "set '%s'->'%s'", setconfCmd, setconfPayload);
        sendLog(logBuf, LOGLEVEL_VERBOSE);

        setConfig(setconfCmd, setconfPayload);
      }
    }

    #ifdef DEBUGMODE
    else if (strncmp(cmdPayload_lower, "get eeprom", 10) == 0)
    {
      getEEPROMContent();
    }
    #endif

    else if (strncmp(cmdPayload_lower, "get ", 4) == 0)
    {
      char buf[81];
      char setconfCmd[16];

      uint8_t len = strlen(cmdPayload) - 4;
      for (int i = 0; i < len; i++)
      {
        if (i < 81)
          buf[i] = cmdPayload[i + 4];
      }
      if (len <= (sizeof(buf) - 1))
        buf[len] = '\0';
      else
        buf[(sizeof(buf) - 1)] = '\0';

#ifdef DEBUG_VERBOSE
      Serial.print("Buf: ");
      Serial.println(buf);
#endif

      uint8_t setconfCmdLen = 0;
      for (int i = 0; i < len; i++)
      {
        //if (buf[i] == 32 || buf[i] == '\0') break; // if SPACE command name is finished, if \0 command parameter is missing
        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58)
          break; // if SPACE(32) or =(61) or :(58) command name is finished
        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13)
        { // if \0, LF (10) or CR (13) command parameter is missing
          break;
        }
        setconfCmd[i] = buf[i];
        setconfCmdLen++;
      }
      setconfCmd[setconfCmdLen] = '\0';
      yield();
#ifdef DEBUG_VERBOSE
      Serial.print("setconfCmd: '");
      Serial.print(setconfCmd);
      Serial.println("'");
#endif
      snprintf(logBuf, LOG_BUFFER_SIZE, "get '%s'", setconfCmd);
      sendLog(logBuf);
      getConfig(setconfCmd);
    }

    /*else if (strncmp(cmdPayload, "enc ", 4) == 0) {
      char buf[81];
      char setconfCmd[16];

      uint8_t len = strlen(cmdPayload) - 4;
      for (int i = 0; i < len; i++) {
        if (i < 81) buf[i] = cmdPayload[i + 4];
      }
      if (len <= (sizeof(buf)-1)) buf[len] = '\0';
      else buf[(sizeof(buf)-1)] = '\0';

#ifdef DEBUG_VERBOSE
      Serial.print("Buf: ");
      Serial.println(buf);
#endif
      
      uint8_t setconfCmdLen = 0;
      for (int i = 0; i < len; i++) {
        //if (buf[i] == 32 || buf[i] == '\0') break; // if SPACE command name is finished, if \0 command parameter is missing
        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58) break; // if SPACE(32) or =(61) or :(58) command name is finished
        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13) { // if \0, LF (10) or CR (13) command parameter is missing
          break;
        }
        setconfCmd[i] = buf[i];
        setconfCmdLen++;
      }
      setconfCmd[setconfCmdLen] = '\0';
      yield();
#ifdef DEBUG_VERBOSE
      Serial.print("setconfCmd: '");
      Serial.print(setconfCmd);
      Serial.println("'");
#endif
      char bufg[50];
      sprintf(bufg, "enc '%s'", setconfCmd);
      sendLog(bufg);

      sprintf(bufg, "%s", XORENC(setconfCmd, encKey));
      sendLog(bufg);
      //getConfig(setconfCmd);
    }*/

    else if (strncmp(cmdPayload_lower, "restart", 7) == 0)
    {
      sendLog(F("restarting..."));
      restart();
    }

    else if (strncmp(cmdPayload_lower, "sysinfo", 7) == 0)
    {
      log_sysdata();
    }

    #ifdef ENABLE_I2C_INTERFACE
    else if (strncmp(cmdPayload_lower, "i2cscan", 7) == 0)
    {
      i2cscan();
    }
    #endif

    //else if (strncmp(cmdPayload_lower, "debugmode 1", 11) == 0)
    //{
    //  sendLog(F("debugmode on"));
    //  sysInfoEverySecond = true;
    //}
//
    //else if (strncmp(cmdPayload_lower, "debugmode 0", 11) == 0)
    //{
    //  sendLog(F("debugmode off"));
    //  sysInfoEverySecond = false;
    //}

    else if (strncmp(cmdPayload_lower, "debug 2", 7) == 0)
    {
      sendLog(F("DEBUG=2"));
      conf_setDebugMode();
      sysInfoEverySecond = true;
    }

    else if (strncmp(cmdPayload_lower, "debug 1", 7) == 0)
    {
      sendLog(F("DEBUG=1"));
      conf_setDebugMode();
      sysInfoEverySecond = false;
    }

    else if (strncmp(cmdPayload_lower, "debug 0", 7) == 0)
    {
      sendLog(F("DEBUG=0"));
      conf_clearDebugMode();
      sysInfoEverySecond = false;
    }

    else if (strncmp(cmdPayload_lower, "debug", 5) == 0)
    {
      snprintf(logBuf, LOG_BUFFER_SIZE, "DEBUG=%d", debug);
      sendLog(logBuf);
    }

#ifdef ENABLE_FEATURE_NTP_TIME
    else if (strncmp(cmdPayload_lower, "date", 7) == 0)
    {
      printDate();
    }
#endif

#ifdef ENABLE_FEATURE_NTP_TIME
    else if (strncmp(cmdPayload_lower, "syncclock", 7) == 0)
    {
      syncClock(true);
    }
#endif

    else if (strncmp(cmdPayload_lower, "clearcreds", 10) == 0)
    {
      confClearCredentials();
    }

    else if (strncmp(cmdPayload_lower, "clearsecrets", 12) == 0)
    {
      #ifdef STORE_SECRETS_IN_EEPROM
        clearSecrets_EEPROM();
      #else
        FS_deleteFile("/confSecrets");
      #endif
    }

    else if (strncmp(cmdPayload_lower, "format eeprom", 13) == 0)
    {
      formatEEPROM_AllData();
    }
    

    else if (strncmp(cmdPayload_lower, "clearwifi", 10) == 0)
    {
      confClearWiFiCredentials();
    }

    else if (strncmp(cmdPayload_lower, "saveconf /f", 11) == 0)
    {
      saveConfig_all(true);
    }

    else if (strncmp(cmdPayload_lower, "saveconf", 8) == 0)
    {
      saveConfig_all();
    }
    

    
    else if (strncmp(cmdPayload_lower, "savevalues", 10) == 0)
    {
      #ifdef FIRMWARE_VARIANT_THERMOSTAT
      thermostat_saveValues();
      #endif
    }

    
    #ifdef ENABLE_FEATURE_SECRETS_ENCRYPTION

    else if (strncmp(cmdPayload_lower, "encryptoff /y", 13) == 0)
    {
      if(confCheckEncrypted()) {
        confEncryptOff();
      }
    }

    else if (strncmp(cmdPayload_lower, "encryptoff", 10) == 0)
    {
      if(confCheckEncrypted()) {
        snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_commands_encryptoff);
        sendLog(logBuf);
      }
    }

    else if (strncmp(cmdPayload_lower, "encrypt /y", 10) == 0)
    {
      confEncrypt();
    }

    else if (strncmp(cmdPayload_lower, "encrypt /f", 10) == 0)
    {
      confEncrypt(true);
    }

    else if (strncmp(cmdPayload_lower, "encrypt", 7) == 0)
    {
      if(!confCheckEncrypted()) {
        snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_commands_encrypt);
        sendLog(logBuf);
        snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_commands_encrypt2);
        sendLog(logBuf);
      }
    }

    else if (strncmp(cmdPayload_lower, "decrypt", 7) == 0)
    {
      if(confCheckEncrypted()) {
        snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_commands_decrypt);
        sendLog(logBuf);
        snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_commands_encryptoff);
        sendLog(logBuf);
      }
    }
    
    #endif


    else if (strncmp(cmdPayload_lower, "ls", 2) == 0)
    {
      FS_listFiles();
    }

    else if (strncmp(cmdPayload_lower, "del ", 4) == 0)
    {
      char _buf[31];
      uint8_t _buf_i=0;
      for(uint8_t _i=4; _i < sizeof(cmdPayload); _i++) {
        if(_buf_i < (sizeof(_buf)-1)) {
          _buf[_buf_i] = cmdPayload[_i];
        _buf_i++;
        }
      }
      _buf[_buf_i] = '\0';
      FS_deleteFile(_buf);
    }

    else if (strncmp(cmdPayload_lower, "rm ", 3) == 0)
    {
      char _buf[31];
      uint8_t _buf_i=0;
      for(uint8_t _i=3; _i < sizeof(cmdPayload); _i++) {
        if(_buf_i < (sizeof(_buf)-1)) {
          _buf[_buf_i] = cmdPayload[_i];
        _buf_i++;
        }
      }
      _buf[_buf_i] = '\0';
      FS_deleteFile(_buf);
    }

    else if (strncmp(cmdPayload_lower, "ren ", 4) == 0)
    {
      char _buf_fileFrom[51];
      char _buf_fileTo[51];

      uint8_t _startFromChar = 4;

      // 1st parameter
      uint8_t _buf_i=0;
      for(uint8_t _i = _startFromChar; _i < sizeof(cmdPayload); _i++) {
        if(_buf_i < (sizeof(_buf_fileFrom)-1)) {
          if(cmdPayload[_i] == ' ') break;
          else {
            _buf_fileFrom[_buf_i] = cmdPayload[_i];
            _buf_i++;
          }
        }
      }
      _buf_fileFrom[_buf_i] = '\0';

      //snprintf(logBuf, LOG_BUFFER_SIZE, "ren: 1st='%s', _buf_i=%d", _buf_fileFrom, _buf_i);
      //sendLog(logBuf);

      // 2nd parameter
      _startFromChar += _buf_i + 1;
      uint8_t _buf_i2=0;
      for(uint8_t _i = _startFromChar; _i < sizeof(cmdPayload); _i++) {
        if(_buf_i2 < (sizeof(_buf_fileTo)-1)) {
          if(cmdPayload[_i] == ' ') break;
          else {
            _buf_fileTo[_buf_i2] = cmdPayload[_i];
            _buf_i2++;
          }
        }
      }
      _buf_fileTo[_buf_i2] = '\0';

      //snprintf(logBuf, LOG_BUFFER_SIZE, "ren: 2nd='%s', _buf_i2=%d", _buf_fileTo, _buf_i2);
      //sendLog(logBuf);

      //snprintf(logBuf, LOG_BUFFER_SIZE, "ren '%s' to '%s'", _buf_fileFrom, _buf_fileTo);
      //sendLog(logBuf);

      FS_renameFile(_buf_fileFrom, _buf_fileTo);
    }

    else if (strncmp(cmdPayload_lower, "ipcfg", 5) == 0)
    {
      printIpcfg();
    }

    else if (strncmp(cmdPayload_lower, "help", 4) == 0)
    {
      cmdPrintHelp();
    }

    else if (strncmp(cmdPayload_lower, "mqttreset", 9) == 0)
    {
      mqttResetConnection();
    }

    else if (strncmp(cmdPayload_lower, "mqttinfo", 8) == 0)
    {
      mqtt_publishStatus();
    }

    else if (strncmp(cmdPayload_lower, "getconf", 7) == 0)
    {
      sendLog(F("CONF: listing all conf parameters:"));
      getConfig((char *)"confDevWiFi");
      getConfig((char *)"confWeb");
      getConfig((char *)"confMqtt");
      getConfig((char *)"confAdd");
      getConfig((char *)"confTime");
      getConfig((char *)"confLog");
      getConfig((char *)"confSens");
      #ifdef FIRMWARE_VARIANT_THERMOSTAT
      getConfig((char *)"confTherm");
      getConfig((char *)"confThermAdv");
      #endif
      #ifdef FIRMWARE_VARIANT_HEATCONTROL
      getConfig((char *)"confHeatc");
      #endif
      sendLog(F("------"));
    }
    else if (strncmp(cmdPayload_lower, "delconf", 7) == 0)
    {
      sendLog(F("deleting configuration..."));
      deleteConfig();
    }

    #ifdef ENABLE_SENSORS_ONEWIRE
      else if (strncmp(cmdPayload_lower, "sensassign", 10) == 0)
      {
        oneWireSensors_loadAssignments(true);
      }

      else if (strncmp(cmdPayload_lower, "sensshow", 8) == 0)
      {
        oneWireSensors_show();
      }
    #endif

    cmdInQueue = false;
  }
}

void cmdPrintHelp()
{
  sendLog(F("valid commands:"));
  sendLog(F("   sysinfo       show uptime, heap usage..."));
  sendLog(F("   date          show current date/time"));
  sendLog(F("   syncclock     perform NTP time sync now"));
  sendLog(F("   debug [0/1]"));
  sendLog(F("   loadconf      load saved configuration"));
  sendLog(F("   getconf       list all conf parameters"));
  sendLog(F("   get [PARAM]   show conf value"));
  sendLog(F("   get values    list current saved values"));
  sendLog(F("   set [PARAM] [VALUE] (1 blank after PARAM to clear)"));
  sendLog(F("   saveconf      save all configurations"));
  sendLog(F("   savevalues    save set values"));
  sendLog(F("   clearcreds    delete all passwords"));
  sendLog(F("   clearwifi     delete WiFi configurations"));
  sendLog(F("   mqttinfo      MQTT connection status"));
  sendLog(F("   mqttreset     reset MQTT connection"));
  sendLog(F("   encrypt       switch on encrypted stored passwords"));
  sendLog(F("   decrypt       switch off encrypted stored passwords"));
  sendLog(F("                 WARNING: deletes all currently saved credentials"));
  #ifdef ENABLE_SENSORS_ONEWIRE
  sendLog(F("   "));
  sendLog(F("   sensshow      list OneWire sensors"));
  sendLog(F("   sensassign    (re)load OneWire sensor assignments"));
  #endif
  sendLog(F("   "));
  sendLog(F("   ls            list files on File System"));
  sendLog(F("   del [name]    delete a file on File System"));
  sendLog(F("   ren [name]    rename a file on File System"));
  sendLog(F("   "));
  sendLog(F("   delconf       delete ALL configuration"));
  sendLog(F("   restart"));
}
