#include <Arduino.h>

using namespace std;

#define DEBUG 0

#if DEBUG == 1
  #define debug(x) Serial.print(x)
  #define debugln(x) Serial.println(x)
#else
#define debug(x)
#define debugln(x)  
#endif

//(data type) (tag) 
struct storage
{// (members)
  char *temp;   // comma.temp - Temp holder for returned parsed string prior to coping to comma.result
  char result[10][50]; // comma.result copied from comma.temp
  int index;  // comma.index returned index location of pointer
  byte size[10];  // comma.size - Size of the returned string
  int location[10]; // comma.location
  int upnext; // comma.next = Returned index ptr of location of the next found 

};

storage colon;
storage comma;
storage lBracket;
storage rBracket;
//Structure Notes
  //Structure Definition
  //Method 1    
  //(Data Specifier) (structue tag) (variable name)
  //struct storage colon;


  //Method 2 
  /*
  {// (members)
    char colonI[10][50]; // Colon Index
    char commaI[10][50]; // Comma Index
    char lbrI[10][50];   // Left Bracket Index
    char rbrI[10][50];   // Right Bracket Index
      ↓--Definition
  }colon, comma lbrIndex, rbrIndex;
  */
//
//Template for array Dictionary
  const char parsedStrings[15][15] = {" "};
  // 0-0 = (set)
  // 0-1 = (remove)
  // 0-2 = (get)
  // 0-3 = (clear)
  // 1-0 = (function)
  // 1-1 = (wifi)
  // 1-2 = (ble"bluetooth")
  // 3-0 = (#)
  // 3-1 = (ssid,password,ip,hostname,gateway,dns)
  // 4-0 = (on,off,fillall,bright,fade,effect,delay,rgb,saturation)
  // 5-0 = (up,down,add,red,green,blue)
///
char colonIndex[10][50];
char commaIndex[10][50];
char lbrIndex[10][50];
char rbrIndex[10][50];

//Command variables
  const char* request[][15] = {
      "set",      //  [0]
      "get",      //  [1]
      "clear",    //  [2]
      "read",     //  [3]
      "write",    //  [4]
    };
  const char* fuction[][10] = {
      "function",
      "effect",
      "spiffs",
      "status",
      "arrays",
    };
  const char* key1[][10] = {
      "fillall",
      "bright",
      "effect",
      "fade",
      "wifi",
      "ble",
    };

  const char* actions[][10] = {
      "up",
      "down",
      "add",
      "remove",
      "on",
      "off",
    };

  const char* attributes[][15] = {
      "rgb",
      "red",
      "green",
      "blue",
      "hue",
      "saturation",
      "fade",
      "speed",
    };
  const char* Answers[][10] = {
      "no",
      "yes",
    };
////
void SetAction() {

  }


// no return
void MultiParse(char* s, char d, char e) {
    char* input = s; 
    char* result2 = new char[strlen(input) + 1];

    for(int i = 0; i <= strlen(input); i++) {
      int j = i + 1;
      if (input[i] != d && input[j] != e) {
        result2[i] = input[i];
      }
      else {
        result2[i] = '\0';
        //int tempsize = strlen(tmpSTR)
        return result2;
        }
      }
      return result2;
    }




//with return
char* MultiParse(char* s, char d, char e) {
    char* input = s; 
    char* result2 = new char[strlen(input) + 1];

    for(int i = 0; i <= strlen(input); i++) {
      int j = i + 1;
      if (input[i] != d && input[j] != e) {
        result2[i] = input[i];
      }
      else {
        result2[i] = '\0';
        //int tempsize = strlen(tmpSTR)
        return result2;
        }
      }
      return result2;
    }




char* Parser(char* tempInput, char d, int* ndxptr, int* nxt) {
    // Stores the state of string
    static char* input = NULL;
    // Initialize the input string
    if (tempInput != NULL){
        debugln("tempInput");
        input = tempInput;
        }
    // Case for final token
    if (input == NULL) {
        debugln("input");
        return "\0";
      }
        // Stores the extracted string
        char* result = new char[strlen(input) + 1];
      int i = 0;
    
        // Start extracting string and
        // store it in array
        // If not at the end of the array
        // Keep looking through
      for (; input[i] != '\0'; i++) {
        // If current character is not
        // equal to the delimiting char
        // assign to result
        if ( input[i] != d ) {
          debugln("if");
          result[i] = input[i];
          *ndxptr = *ndxptr + 1;
          *nxt+= 1;
          }
        // Else store the string formed
        // and set t
        else {
          debugln("else");
          result[i] = '\0';
          debugln(input);
          // Moves the pointer of the first
          // char to the next delimiter + 1
          *ndxptr = *ndxptr + 1;
          *nxt = *nxt + 1;
          input = input + i + 1;
          debugln(input);
          return result;
        }
      }
      debugln("end");
      result[i] = '\0';
      input = NULL;
      return result;
    } 
/////
void ReadSerial() {
  char parsedStrings[10][100];
  char userInput[75] = "";
    while(Serial.available() > 0) {
      size_t numChars = Serial.readBytesUntil('\n', userInput, sizeof(userInput) - 1);
      userInput[numChars] = '\0'; 
        printf("You entered: %s\n", userInput);

    // This captures the count of characters read
    // and is not zero indexed like an array would be
    printf("\n");
    int userInputSize = strlen(userInput);
    printf("Size of userInput = %i\n", userInputSize);

    // To get the count to compare to a string
    // remove one from the total
    int totalChars = userInputSize - 1;

    //parser(&userInput[0], ':');
      //printf("index = %s\n", charIndex[0])  ; 

    //Find the index location
    //size_t colIndex = strcspn(userInput, ":");
    //printf("Location of colon =  %i\n", colIndex);




// within he input ou will have  Set, get, clear, read, write
// store these strings in an arrayh they will hen each have an 
// index value you can use to cross reference with another array
// 

  //------------------Comma
    printf("\n");
    int com = 0;
    byte comSize[10];
    int comLocation[10];
    int nxt = 0;
    int upNext = nxt;
    int ndxptr = 0;

    comma.index = 0;

    //char* tempComma = Parser(userInput, ',', &ndxptr, &nxt);   
    comma.temp = Parser(userInput, ',', &ndxptr, &nxt); 
    upNext = nxt;  
    comma.size[comma.index] = strlen(comma.temp);
    comma.location[comma.index] = ndxptr;

    if (strlen(comma.temp) > 0 && strlen(comma.temp) < totalChars) {
      strcpy(comma.result[comma.index], comma.temp);
      //strcpy(aIndex[com], colon.temp);
      printf("Next location with delimiter = %d\n", upNext);
      printf("Comma %i: %s\t Location: %d\n",comma.index, comma.result[comma.index], comma.location[comma.index]);   
      comma.index++;  
    }

    while(comma.temp != "\0") {
    comma.temp = Parser(NULL, ',', &ndxptr, &nxt);
      upNext = nxt;  
      comma.size[comma.index] = strlen(comma.temp);
      comma.location[comma.index] = ndxptr;

      if (strlen(comma.temp) > 0 && strlen(comma.temp) < totalChars) {
        strcpy(comma.result[comma.index], comma.temp);
        printf("Next location with delimiter = %d\n", upNext);
        printf("Comma %i: %s\t Location: %d\n",comma.index, comma.result[comma.index], comma.location[comma.index]);   
        comma.index++;
        }
      }


  //------------------Colon
    printf("\n");
    int col = 0;
    byte colSize[10];
    int colLocation[10];
    ndxptr = 0;
    nxt = 0;

    char* tempColon = Parser(userInput, ':', &ndxptr, &nxt);
    upNext = nxt;
    colSize[col] = strlen(tempColon);
    colLocation[col] = ndxptr;
      if (strlen(tempColon) > 0 && strlen(tempColon) < totalChars) {
        strcpy(colonIndex[col], tempColon);
        printf("Next location with delimiter = %d\n", upNext);
        printf("Colon: %i: %s\t Location: %d\n",col, colonIndex[col], colLocation[col]);
        col++;
      }
    while(tempColon != "\0") {
    tempColon = Parser(NULL, ':', &ndxptr, &nxt);
      upNext = nxt;  
      colSize[col] = strlen(tempColon);
      colLocation[col] = ndxptr;

        if (strlen(tempColon) > 0 && strlen(tempColon) < totalChars) {
          strcpy(colonIndex[col], tempColon);
          printf("Next location with delimiter = %d\n", upNext);
          printf("Colon: %i: %s\t Location: %d\n",col, colonIndex[col], colLocation[col]);  
          col++;
          }
        } 
  //------------------Left Bracket    
    printf("\n");
    int lbr = 0;
    byte lbrSize[10];
    int lbrLocation[10]; 
    ndxptr = 0;
    nxt = 0;

    char* lbrTemp = Parser(userInput, '[', &ndxptr, &nxt);
      upNext = nxt;  
      lbrSize[lbr] = strlen(lbrTemp);
      lbrLocation[lbr] = ndxptr;

    if (strlen(lbrTemp) > 0 && strlen(lbrTemp) < totalChars) {
      strcpy(lbrIndex[lbr], lbrTemp);
      printf("Next location with delimiter = %d\n", upNext);
      printf("Left Bracket %i: %s\t Location: %d\n", lbr, lbrIndex[lbr], lbrLocation[lbr]);  
      lbr++;
      } 
      
    while(lbrTemp != "\0") {
    lbrTemp = Parser(NULL, '[', &ndxptr, &nxt);
      upNext = nxt;
      lbrSize[lbr] = strlen(lbrTemp);  
      lbrLocation[lbr] = ndxptr;

      if(strlen(lbrTemp) > 0 && strlen(lbrTemp) < totalChars) {
        strcpy(lbrIndex[lbr], lbrTemp);
        printf("Next location with delimiter = %d\n", upNext);
        printf("Left Bracket %i: %s\t Location: %d\n", lbr, lbrIndex[lbr], lbrLocation[lbr]);
        //printf("lbrIndex length is %i\n", strlen(lbrIndex[lbr]));
        lbr++;
        }
      }

  //------------------Right Bracket
    printf("\n");
    int rbr = 0;
    byte rbrSize[10];
    int rbrLocation[10];
    ndxptr = 0;
    nxt = 0;

    char* rbrTemp = Parser(userInput, ']', &ndxptr, &nxt);
      upNext = nxt;
      rbrSize[rbr] = strlen(rbrTemp);
      rbrLocation[rbr] = ndxptr;

        if (strlen(rbrTemp) > 0 && strlen(rbrTemp) < totalChars) {
          strcpy(rbrIndex[rbr], rbrTemp);
          printf("Next location with delimiter = %d\n", upNext);
          printf("Right Bracket #%i is %s and located at %d\n", rbr, rbrIndex[rbr], rbrLocation[rbr]);
          //printf("rbrIndex length is %i\n", strlen(rbrIndex[rbr]));
          rbr++;
        } 

    while(rbrTemp != "\0") {
      rbrTemp = Parser(NULL, ']', &ndxptr, &nxt);
      upNext = nxt;
      rbrSize[rbr] = strlen(rbrTemp);
      rbrLocation[rbr] = ndxptr;

      if(strlen(rbrTemp) > 0 && strlen(rbrTemp) < totalChars) {
        strcpy(rbrIndex[rbr], rbrTemp);
        printf("Next location with delimiter = %d\n", upNext);
        printf("Right Bracket #%i is %s and located at %d\n", rbr, rbrIndex[rbr], rbrLocation[rbr]);
        //printf("rbrIndex length is %i\n", strlen(rbrIndex[rbr]));
        rbr++;
      }
      else if(userInput[userInputSize] == ']') {
        printf("Right Bracket #%i is %s and located at %d\n", rbr, rbrIndex[rbr], rbrLocation[rbr]);
        }
      }
    }

    if ( strncmp (lbrIndex[0], "set", int(3)) == 0) {
      printf("Triggered: SET\n");
      SetAction();
      
    }
  }    


void setup() {
  Serial.begin(115200);
  delay(100);
 /*
  struct storage colon;
  struct storage comma;
  struct storage rBracket;
  struct storage lBracket;
 */
    }

void loop() {
  delay(10); // this speeds up the simulation

  if(Serial.available() > 0) {
    //debugln("reading serial in loop");
    ReadSerial();
    }
  }