#include "LList.h"

LCList gCList;


 uint16_t  gLngCnt = 0;
 uint16_t  gLngOrig = 0;
 uint16_t  gLngDiff = 0;


#define INP_01 35
 bool  gInput1Status = false;
 unsigned long  gInput1DelayCnt = 0;
 unsigned long  gInput1WaitCnt = 0;
 bool  gInput2Status = false;
 unsigned long  gInput2DelayCnt = 0;
 unsigned long  gInput2WaitCnt = 0;
 bool  gInput3Status = false;
 unsigned long  gInput3DelayCnt = 0;
 unsigned long  gInput3WaitCnt = 0;
 
 byte InpStt1 = 1;
 byte InpDly1 = 3;
 byte InpStt2 = 0;
 byte InpDly2 = 3;
 byte InpStt3 = 0;
 byte InpDly3 = 3;
 byte InpWttOn1 = 5;
 byte InpWttOff1 = 5;

//String gStr = "\t{\n\t\t\"user\": {\n\t\t\t\"id\": \"76909417-185c-4ff7-8132-c3463bafe674\",\n\t\t\t\"name\": \"leo\",\n\t\t\t\"email\": \"[email protected]\",\n\t\t\t\"avatar\": null,\n\t\t\t\"type\": \"engenharia\",\n\t\t\t\"created_at\": \"2022-05-31T22:40:00.060Z\",\n\t\t\t\"updated_at\": \"2022-05-31T22:40:00.060Z\",\n\t\t\t\"avatar_url\": null\n\t\t},\n\t\t\"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.DyJpc0FkbWluIjpmYWxzZSwidHlwZSI6ImVuZ2VuaGFyaWEiLCJpYXQiOjE2NjI2NTYyNzAsImV4cCI6MTY5NDE5MjI3MCwic3ViIjoiNzY5MDk0MTctMTg1Yy00ZmY3LTgxMzItYzM0NjNiYWZlNjc0In0.C2fgLObA62221IkRLOB3FyRUg8YBESwfW6KhxuPWLXk\"\n\t}";

String gStr2 = "meu";

String StrZPad(uint8_t pLenChar){
  String vRet = "";
  for(int vI=0; vI < pLenChar; vI++){ 
  vRet += "0";
  }
  return vRet;
}

//Convert StringHex para ArrayByte, 
// ArrDest = array destino, pDestPosI =posic.inical no array, 
// pStr = String com coidigo Hex, pStrPosi = posicao inical na pStr, 
// pStrLen=Caract para ler (em Char, 1byte = 2),
// pLE(LittleEndian) = formato (true=invertido, 258=0102; false=normal, 258=0102), i.e: pLE==true irá inverter
// pType = 0:LE->LE 1:LE->BE 2:BE->LE 3:BE->BE  
// pStrByteLen qtt char to read in pStr
// pDestByteLen: Max bytes(2 char) to Dest  
String StringHexFormat(String pStr, uint8_t pStrPosI, uint8_t pStrLen,  uint8_t pDestByteLen, uint8_t pType) {
        String vStrOrigUtil = "";
        uint8_t pDestCharLen = pDestByteLen*2;
        int8_t  vOrigCharLen = pStr.length()-pStrPosI; //util = comp pStr - menos posicao inicio
        if (vOrigCharLen<0){vOrigCharLen=0;}
        if (pStrLen>0 && pStrLen<vOrigCharLen) {vOrigCharLen=pStrLen;} //se comp estecificado é >0 e menor que comp util, usa-lo 
        if (vOrigCharLen > pDestCharLen) {vOrigCharLen = pDestCharLen;} //se string util maior que destino, utilizar destino
        uint8_t vErr = vOrigCharLen%2; //(0 se ok, 1 se LE err);
        if (pType > 1 && vOrigCharLen < pDestCharLen){ //falta zeros & origemBE = zero esquerda
          vStrOrigUtil = StrZPad(pDestCharLen-vOrigCharLen);
          vErr = 0;//Erro corrigido
        }
        vStrOrigUtil += pStr.substring(pStrPosI, (pStrPosI+vOrigCharLen-vErr));
        if (vErr == 1){
          vStrOrigUtil += "0";
          vStrOrigUtil += pStr.substring((pStrPosI+vOrigCharLen-vErr), (pStrPosI+vOrigCharLen));
        }
        if (vStrOrigUtil.length()<pDestCharLen){
          vStrOrigUtil += StrZPad(pDestCharLen-vStrOrigUtil.length());
        }
        String vStrConv = "";
        if (pType == 1 || pType == 2){//invert
          for (int iCnt = pDestCharLen-2; iCnt >=0; iCnt-=2)
          {
            //Serial.print(iCnt);
            vStrConv += vStrOrigUtil.substring(iCnt, iCnt+2);
          }
        } else {
          vStrConv = vStrOrigUtil;
        }
        return vStrConv;
    }


//Convert StringHex para ArrayByte, 
// ArrDest = array destino, pDestPosI =posic.inical no array, 
// pStr = String com coidigo Hex, pStrPosi = posicao inical na pStr, 
// pStrLen=Caract para ler (em Char, 1byte = 2),
// pLE(LittleEndian) = formato (true=invertido, 258=0102; false=normal, 258=0102), i.e: pLE==true irá inverter
// pType = 0:LE->LE 1:LE->BE 2:BE->LE 3:BE->BE  
// pStrByteLen qtt char to read in pStr
// pDestByteLen: Max bytes(2 char) to Dest  
void StringHexToByte(byte arrDest[], int pDestPosI, String pStr, uint8_t pStrPosI, uint8_t pStrLen,  uint8_t pDestByteLen, uint8_t pType) {
       
        String vStrConv = StringHexFormat(pStr, pStrPosI, pStrLen,  pDestByteLen, pType);
        for (int iCnt = 0; iCnt < pDestByteLen; iCnt++)
        {
             arrDest[pDestPosI+iCnt]=(uint8_t) strtol(vStrConv.substring((iCnt*2), (iCnt*2)+2).c_str(), NULL, 16);
        }

        for (int iCnt = pDestPosI; iCnt < (pDestPosI+pDestByteLen); iCnt++)
        {Serial.print((int) arrDest[iCnt]);Serial.print(":");}
    }

uint8_t StringHexToU8(String pStr, int pStrPosI) {
    //uint8_t objRet = 0;
	  byte vRet[1];
    StringHexToByte(vRet, 0, pStr, pStrPosI, 2, 1, 0);
    return vRet[0];
}

uint32_t StringHexToU32(String pStr, int pStrPosI, bool pLE=true) {
    //uint8_t objRet = 0;
	  byte vVal[4] = {0,0,0,0};
    uint32_t vRet = 0; // = 0;
    StringHexToByte(vVal, 0, pStr, pStrPosI, 8, 4, (pLE)?0:2);
    Serial.print(vVal[0]);Serial.print(":");
    Serial.print(vVal[1]);Serial.print(":");
    Serial.print(vVal[2]);Serial.print(":");
    Serial.println(vVal[3]);
    memcpy(&vRet, vVal, sizeof(vRet)); //(funcion com char invertido = littleendian)
    return vRet;
    //return vRet[0] + (vRet[1]*256) + (vRet[2]*65536) + (vRet[3]*16777216); //endian
    //Notendian:
//    vRet = vVal[3] ;                  // put the LSB in place
//    vRet |= uint32_t(vVal[2]) << 8;  // add next byte
//    vRet |= uint32_t(vVal[1]) << 16; // add next byte
//    vRet |= uint32_t(vVal[0]) << 24; // add MSB
//    return vRet;
}

String U32ToHex(uint32_t pValue, bool pLE=true) {
    String vRet = ""; 
    vRet = String(pValue, HEX);
    Serial.print(".");
    Serial.println(vRet);
    return StringHexFormat(vRet, 0, vRet.length(), 4, (pLE)?2:3);
}

String gLastCard = "";

uint8_t SecToU8(String pSec){
  uint8_t vRet = 0;
  Serial.println(pSec);
  Serial.println(pSec.toInt());
  if (pSec="of"){ vRet = 99;}
  else {
    vRet = pSec.toInt();
  }

  return vRet;
}

unsigned long gmillisdiff = 0;
    unsigned long milliss(){
        return millis() + gmillisdiff;
    };


bool gInputTst = true; //true = off

#include "LInput.h"

byte   gGParams_InpStt1     = 1;
byte   gGParams_InpDly1     = 10;
byte   gGParams_InpWttOn1   = 2;
byte   gGParams_InpWttOff1  = 2;
byte   gGParams_InpWttRpt1  = 32;
lInput gInp_01(INP_01);


byte gTstSeq = 0;
unsigned long TstTmrCnt = 0;
unsigned long TstTmrComp = 10;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");


  Serial.println(sizeof(gLngCnt));
  
  gLngCnt = 0;
  gLngOrig = gLngCnt;
  Serial.print(gLngCnt);
  gLngDiff = (gLngCnt-gLngOrig);

  while(gLngDiff<= 5){
  Serial.print(":");
  Serial.print(gLngDiff);
  gLngCnt++;
  gLngDiff = (gLngCnt-gLngOrig);
  }
  Serial.println("");

  gLngCnt = 0;
  gLngCnt -= 1;
  gLngOrig = gLngCnt;
  Serial.print(gLngCnt);
  gLngDiff = (gLngCnt-gLngOrig);
  while(gLngDiff<= 5){
  Serial.print(":");
  Serial.print(gLngDiff);
  gLngCnt++;
  gLngDiff = (gLngCnt-gLngOrig);
  }
 Serial.println("");


  gLngCnt = 0;
  gLngCnt -= 4;
  gLngOrig = gLngCnt;
  Serial.print(gLngCnt);
  gLngDiff = (gLngCnt-gLngOrig);
  while(gLngDiff<= 5){
  Serial.print(":");
  Serial.print(gLngDiff);
  gLngCnt++;
  gLngDiff = (gLngCnt-gLngOrig);
  }
  Serial.println("");
 
  gLngCnt = 0;
  gLngCnt -= 5;
  gLngOrig = gLngCnt;
  Serial.print(gLngCnt);
  gLngDiff = (gLngCnt-gLngOrig);
  while(gLngDiff<= 5){
  Serial.print(":");
  Serial.print(gLngDiff);
  gLngCnt++;
  gLngDiff = (gLngCnt-gLngOrig);
  }
  Serial.println("");
 
  gLngCnt = 0;
  gLngCnt -= 6;
  gLngOrig = gLngCnt;
  Serial.print(gLngCnt);
  gLngDiff = (gLngCnt-gLngOrig);
  while(gLngDiff<= 5){
  Serial.print(":");
  Serial.print(gLngDiff);
  gLngCnt++;
  gLngDiff = (gLngCnt-gLngOrig);
  }
Serial.println("");




  

	pinMode(INP_01, INPUT_PULLUP);
  gInp_01.SetTimeForEE(gGParams_InpStt1, gGParams_InpWttOn1,gGParams_InpWttOff1,gGParams_InpWttRpt1);
  

	InpStt1 = 2;
	//Serial.println(MountSelect("0(Normal)1(Alta)", "1"));

  Serial.println(394494, HEX);

  Serial.println(gCList.Size());



  gLastCard = "FE0406";

  
  byte vVal[4] = {0,0,0,0};
  //StringHexToByte(vVal, 0, gLastCard, 0, 8, true);
  //StringHexToByte(vVal, 0, gLastCard, 0, 8, false);


/*
  Serial.println(StringHexToU8(gLastCard, 0));
  Serial.println(StringHexToU8(gLastCard, 2));
  Serial.println(StringHexToU8(gLastCard, 4));
  Serial.println(StringHexToU8(gLastCard, 6));

 Serial.println("-----");
  
  Serial.println(StringHexToU32("D0FE0406", 0));
  Serial.println(StringHexToU32("D0FE040605", 0));

  Serial.println(StringHexToU32(gLastCard, 0));
  Serial.println(StringHexToU32(gLastCard, 2));
  Serial.println(StringHexToU32(gLastCard, 4));
  Serial.println(StringHexToU32(gLastCard, 6));
  Serial.println("-----");
  Serial.println(StringHexToU32("D0FE0406", 0, false));
  
  Serial.println(StringHexToU32(gLastCard, 0, false));
  Serial.println(StringHexToU32(gLastCard, 2, false));
  //Serial.println(StringHexToU32(gLastCard, 4, false));
  //Serial.println(StringHexToU32(gLastCard, 6, false));
  
Serial.println("-----");
  Serial.println(StringHexFormat(gLastCard, 0, gLastCard.length(), 4, 2));
  Serial.println(StringHexFormat(gLastCard, 2, gLastCard.length()-2, 4, 2));
Serial.println("-----");
  Serial.println(U32ToHex(11254521));


  String vSec = "3";
  Serial.println(SecToU8(vSec));
  vSec = "03";
  Serial.println(SecToU8(vSec));
*/
/*
Serial.println("-----");
Serial.println(U32ToHex(130187882));
Serial.println(U32ToHex(130187882, false));
Serial.println("-----");
  Serial.println(StringHexFormat("FE046", 0, 3, 4, 0));//lele
  Serial.println(StringHexFormat("FE046", 0, 3, 4, 1));//lebe
  Serial.println(StringHexFormat("FE046", 0, 3, 4, 2));//bele
  Serial.println(StringHexFormat("FE046", 0, 3, 4, 3));//bebe
*/



  //4294967295
  //4 294 967 295

  gmillisdiff =  (4294967295 - 15000 - millis());
  Serial.println(millis());
}








int gCount = 0;
String vSRead = "";
LCList::QCard vCRead;

uint32_t gSimul = 200;

void loop() {
  // put your main code here, to run repeatedly:
  
  if ((milliss() - TstTmrCnt) > TstTmrComp){
    if (gTstSeq == 0){ //inicio
      //apertta botão por 100ms
      gTstSeq++;  //aperta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print(millis());
      Serial.print(":");
      Serial.println(milliss());
      Serial.print("c");
    } else if (gTstSeq == 1){ //espera off por 100ms
      //apertta botão por 100ms
      gTstSeq++;  //solta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    } else if (gTstSeq == 2){ //inicio
      //apertta botão por 100ms
      gTstSeq++;  //aperta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print("c");
    } else if (gTstSeq == 3){ //espera off por 100ms
      //apertta botão por 100ms
      gTstSeq++;  //solta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    } else if (gTstSeq == 4){ //inicio
      //apertta botão por 100ms
      gTstSeq++;  //aperta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print("c");
    } else if (gTstSeq == 5){ //espera off por 100ms
      //apertta botão por 100ms
      gTstSeq=10;  //solta por 
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    }
//-------------------------------------------------------
     else if (gTstSeq == 10){ //inicio
      //apertta botão por 250ms
      gTstSeq++;  //aperta por
      TstTmrComp = 250;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print("c");
    } 
  //-----------------------------------------------------
    else if (gTstSeq == 11){ //espera off por 100ms
      //apertta botão por 100ms
      gTstSeq++;  //solta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    } else if (gTstSeq == 12){ //inicio
      //apertta botão por 100ms
      gTstSeq++;  //aperta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print("c");
    } else if (gTstSeq == 13){ //espera off por 100ms
      //apertta botão por 100ms
      gTstSeq++;  //solta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    } else if (gTstSeq == 14){ //inicio
      //apertta botão por 100ms
      gTstSeq++;  //aperta por
      TstTmrComp = 100;
      TstTmrCnt = milliss();
      gInputTst = false;     //apertado
      Serial.print("c");
    
    //--------------------------------------------------------
    } else if (gTstSeq == 15){ //espera off por 250ms
      //apertta botão por 100ms
      gTstSeq++; 
      TstTmrComp = 250;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    } else if (gTstSeq == 16){ //espera off por 3s e reinicia
      //apertta botão por 100ms
      gTstSeq = 0; 
      TstTmrComp = 3000;
      TstTmrCnt = milliss();
      gInputTst = true;     //solto
      Serial.print("o");
    }
  }

/*
  if (Serial.available()) {
    vSRead = "";
    vSRead = Serial.readString();
    vSRead = vSRead[0]; // RemoveLF(vSRead);
  } else {
    vSRead = "";
  }

  if(vSRead=="l"){

    LCList::QCard vCard;
    vCard.Sec = 1;
    vCard.Time = 1000;
    gCList.WriteNext(&vCard); //adiciona um card
    Serial.println(gCList.Size()); 
    vCard.Sec = 2;
    vCard.Time = 1001;
    gCList.lLst.push_back(vCard); //adiciona 2o card
    Serial.println(gCList.Size());
    vCard.Sec = 3;
    vCard.Time = 1002;
    gCList.WriteNext(&vCard); //adiciona 3o Card
    Serial.println(gCList.Size());
    

    
  }
  if(vSRead=="k"){  //lista todos os cards
    Serial.println(gCList.Size());
    std::vector<LCList::QCard>::iterator it;
    for (it = gCList.lLst.begin(); it < gCList.lLst.end(); it++)
    {
      Serial.print((*it).Sec);
      Serial.print(":");
      Serial.print((*it).Time);
      Serial.print(":");
      Serial.println((*it).TmSended);
    }
  }
  if(vSRead=="j"){ //apaga card 1000
    Serial.println(gCList.Size());
    Serial.println(gCList.DelMsgId(1, 1000));    
  }
  if(vSRead=="a"){
      if (gCList.PeekNext(&vCRead)){
      Serial.print(vCRead.Sec);
      Serial.print(":");
      Serial.print(vCRead.Time);
      Serial.print(":");
      Serial.println(vCRead.TmSended);
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="s"){
      if (Serial.print(gCList.GoNext())){
      Serial.print(":");
      Serial.print(vCRead.Sec);
      Serial.print(":");
      Serial.println(vCRead.Time);} else {
        Serial.println("Err");
      }
  }
  if(vSRead=="d"){
      if(gCList.ReadNext(&vCRead)){
      Serial.print(vCRead.Sec);
      Serial.print(":");
      Serial.print(vCRead.Time);
      Serial.print(":");
      Serial.println(vCRead.TmSended);
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="h"){
      if(gCList.UpdateTime(200)){
         Serial.println("Ok");
      } else {
        Serial.println("Err");
      }
  }

  if(vSRead=="q"){ //le 1o já enviado
      if (gCList.PeekNextSended(&vCRead, true)){
      Serial.print(vCRead.Sec);
      Serial.print(":");
      Serial.print(vCRead.Time);
      Serial.print(":");
      Serial.println(vCRead.TmSended);
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="w"){ //marca 1001 como enviado
      if (gCList.SetSended(2,1001, 200)){
        Serial.println("enviado 1001");
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="e"){ //le 1o já enviado
      if (gCList.PeekNextSended(&vCRead, false)){
      Serial.print(vCRead.Sec);
      Serial.print(":");
      Serial.print(vCRead.Time);
      Serial.print(":");
      Serial.println(vCRead.TmSended);
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="r"){ //marca 1001 como enviado
      if (gCList.SetSended(1,1000, 200)){
        Serial.println("enviado 1000");
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="t"){ //marca 1001 como enviado
      if (gCList.SetSended(3,1002, 180)){
        Serial.println("enviado 1002");
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="y"){ //marca 1001 como enviado
      if (gCList.DelSended(190)){
        Serial.println("apagou antes 190");
      } else {
        Serial.println("Err");
      }
  }
  if(vSRead=="b"){
    gmillisdiff =  (4294967295 - (3500- gSimul) - millis());    
    Serial.println(gSimul);
  }
  if(vSRead=="n"){
    gSimul -= 50;
    gmillisdiff =  (4294967295 - (3500- gSimul) - millis() );  
    Serial.println("--");
    Serial.println(gSimul);  
  }
  if(vSRead=="m"){
    gSimul += 50;
    gmillisdiff =  (4294967295 - (3500- gSimul) - millis());    
    Serial.println("++");
    Serial.println(gSimul);
  }

  if(vSRead==","){
    gInputTst = false;
  } else if(vSRead=="."){
    gInputTst = true;
  } 
*/



  if(gGParams_InpStt1>0){
  //check Input Status
    gInp_01.Check();
//Serial.print(gInp_01.Value);
//Serial.print(gInputTst);
//Serial.print(",");
//Serial.print(" ");
delay(10);


    if (gInput1DelayCnt > 0){
      //if (milliss() > gInput1DelayCnt )
      if ((milliss()-gInput1DelayCnt)>(gGParams_InpDly1 * 1000))
      {
        gInput1DelayCnt = 0;
        //salva log
        //AddMsg(1);
        Serial.println("MsgODelay");
#ifdef LDSPDEBUG              
        Serial.println("1=doff");
#endif      
      }
    }
    if (!gInp_01.Value){ //off
      if (!gInput1Status){ //permanece = não faz nada
      } else {             // mudou para off
        gInput1Status = false;   
        if (gGParams_InpStt1<3){  //Envia Off se for modo full (não only)
          //AddMsg(1);
          Serial.println("MsgOFF");
        }
#ifdef LDSPDEBUG              
      Serial.println("1=off");
#endif      
      }
    } else {
      if (gGParams_InpDly1 > 0){
          //gInput1DelayCnt = milliss() + (gGParams_InpDly1 * 1000);
          gInput1DelayCnt = milliss();
      }
      if (gInput1Status){ //permanece
      } else { // mudou para on
        gInput1Status = true;
        //AddMsg(1);
        Serial.println("MsgON");
#ifdef LDSPDEBUG              
        Serial.println("1=on");
#endif      
      }
    } 
  }










}