
////////////////////////////////////////////////////////////////////////////////////////////////////
//ANDRUINO LIBRARY
//A.Scavuzzo
//www.andruino.it
////////////////////////////////////////////////////////////////////////////////////////////////////


#define HTTP_ANDRUINO_SITEIP_DNS "andruino.it\0"


char* ethclient_FinishGetStream(char *buffer_rx, byte size_buffer, char *find_char, unsigned int Timeout, keep_alive_type_e keep_alive) {
  bool loop_search = false;

  char *result = 0;
  char *result2 = 0;
  int bufferIndex = 0;
  unsigned long int StartTime;
  boolean ClientStatus = true;
  boolean Timeout_occurred = false;
  boolean currentLineIsBlank = true;
  boolean FoundOnCurrentLine = false;
  boolean AlreadyFound = false;
  boolean exit_while = false;
  byte cmd_i = 0;

  memset(CmdQueue, 0, sizeof(CmdQueue));

  ethbuff_ClientClear();                  //clear the TX buffer before use it
  ethbuff_ClientPrintln(" HTTP/1.1");
  ethbuff_ClientPrint("Host: ");
  ethbuff_ClientPrintln(andruino_it_ip_address);


  if (keep_alive != NO_KEEP_ALIVE) {
    ethbuff_ClientPrintln("Connection: keep-alive");
    ethbuff_ClientPrintln("Keep-Alive: timeout=30, max=100");
  }
  else {
    ethbuff_ClientPrintln("Connection: close");
  }

  ethbuff_ClientPrintln();
  ethbuff_ClientFlush();


  //wait data to be received with a timeout
  StartTime = millis();
  while (!_client.available() && !exit_while) {
    if ((millis() - StartTime) > Timeout) {
#if DEBUG_SERIAL == 1
      Serial.println(F("HTTP NO CONNECTION..."));
#endif
      //if go here, means that the ethernet INIT was fail and so the client is not avaiable
      //when internet is not preset, the code doesn't go here
      //  client_fail_connected_cnt++;
      //  return 0;
      exit_while = true;
    }
  }


  StartTime = millis();
#if DEBUG_SERIAL_PUSH == 1
  Serial.print(F("Start http:")); Serial.println(StartTime);
#endif

  //exit only if timeout occurs or when the end sream is found (NO ERR) and the server has disconnected
  while (!loop_search && (!Timeout_occurred)) {
    if ((millis() - StartTime) > Timeout) {          //exit if timeout occurs
      Timeout_occurred = true;
      break;
    }

    if (_client.available()) {

      char c = _client.read();
#if DEBUG_SERIAL_HTTP_RECEIVE == 1
      Serial.write(c);
#endif
      //when a line is ended, it is parsed
      if (c == '\n') {
        buffer_rx[bufferIndex] = '\0';
        // you're starting a new line

        //find NO ERR keyword
        if (!AlreadyFound) {                                          //if is not yet found
          result = strstr((char *)buffer_rx, find_char);              //find it
          if (result > 0) {                                           //found
            AlreadyFound = true;
#if DEBUG_SERIAL_PUSH == 1
            Serial.print(F("\r\nFound buffer:"));
            Serial.println(buffer_rx);
#endif
          }
        }

        //command from server are decoded
        if (cmd_i < MAX_CMD) {
          result2 = strstr((char *)buffer_rx, "AndruCMD:");              //find it
          //Serial.print(F("result2:")); Serial.println(result2);
          if (result2 > 0) {                                           //found
            //Serial.print(F("Found AndruCMD:"));
            //Serial.println(buffer_rx);
            //Serial.print(F("pointer:"));Serial.println(cmd_i);

            //&cmd=LimAna&port=0&action=0&action2=0&action3=0&action4=0

            json_SearchKeyGET(eth_buffer, "&cmd=", CmdQueue[cmd_i].cmd, sizeof(CmdQueue[cmd_i].cmd), "&");
            json_SearchKeyGET(eth_buffer, "&port=", CmdQueue[cmd_i].port, sizeof(CmdQueue[cmd_i].port), "&");
            json_SearchKeyGET(eth_buffer, "&action=", CmdQueue[cmd_i].action, sizeof(CmdQueue[cmd_i].action), "&");
            json_SearchKeyGET(eth_buffer, "&action2=", CmdQueue[cmd_i].action2, sizeof(CmdQueue[cmd_i].action2), "&");
            json_SearchKeyGET(eth_buffer, "&action3=", CmdQueue[cmd_i].action3, sizeof(CmdQueue[cmd_i].action3), "&");
            json_SearchKeyGET(eth_buffer, "&action4=", CmdQueue[cmd_i].action4, sizeof(CmdQueue[cmd_i].action4), "&");
            json_SearchKeyGET(eth_buffer, "&action5=", CmdQueue[cmd_i].action5, sizeof(CmdQueue[cmd_i].action5), "&");
            char active[2];
            memset(active, 0, sizeof(active));
            if (json_SearchKeyGET(eth_buffer, "&active=", active, sizeof(active), "&")) {
              active_iphone_connection = atoi(active);
              
              //Jan 2020, this speed-up the pass from sleep to active mode
              if(active_iphone_connection)    
                send_http_active_client_req = true;
                
              //Serial.print(F("active_iphone_connection:"));Serial.println(active_iphone_connection);
            }
            //Serial.print(F("\r\ncmd=")); Serial.print(CmdQueue[cmd_i].cmd);Serial.print(F(", port="));Serial.print(CmdQueue[cmd_i].port);Serial.print(F(", action="));Serial.print(CmdQueue[cmd_i].action);Serial.print(F(", action2="));Serial.print(CmdQueue[cmd_i].action2);Serial.print(F(", action3="));Serial.print(CmdQueue[cmd_i].action3);Serial.print(F(", action4="));Serial.print(CmdQueue[cmd_i].action4);Serial.print(F(", action5="));Serial.print(CmdQueue[cmd_i].action5);Serial.print(F(", active="));Serial.println(active);
            cmd_i++;
          }
        }

        bufferIndex = 0;                                              //clear buffer
        buffer_rx[0] = '\0';
        //ethbuff_ClientClear();
      }
      else if (c != '\r') {
        // you've gotten a character on the current line
        if (bufferIndex < ETH_TX_RX_MAX_PACKET - 2 &&  (AlreadyFound == false)) {
          buffer_rx[bufferIndex] = c;                             //fill the buffer
          bufferIndex++;
        }
      }

    } else if (AlreadyFound)
      loop_search = true;
  }


  if (Timeout_occurred == true) {
#if DEBUG_SERIAL == 1
    Serial.println(F(" HTTP TIMEOUT"));
#endif
  }


  if (AlreadyFound) {
    Serial.print(andruino_it_ip_address); Serial.println(F(": OK"));
    client_fail_connected_cnt = 0;
  }
  else {
    Serial.print(andruino_it_ip_address); Serial.println(F(": ERR"));
  }

  if (keep_alive == NO_KEEP_ALIVE) {
    //Serial.println(F("Disconnecting from ANDRUINO.it"));
    _client.flush();
    _client.stop();
    //ethbuff_delay_and_stop();
  }


#if DEBUG_SERIAL_PUSH == 1
  Serial.print(F("End http:")); Serial.println(millis());
#endif


#if DEBUG_SERIAL_CMD == 1
  Serial.print(F("Received AndruCMD:"));
  Serial.println(cmd_i);
#endif


  if (cmd_i > 0) {
    for (byte i = 0; i < cmd_i; i++) {
      if (CmdQueue[i].cmd[0] > 0) {
#if DEBUG_SERIAL_CMD == 1
        Serial.print(F("Exec cmd:")); Serial.println(i);
#endif
        json_PerformRequestedCommand(true, i);
        /*   Serial.print(F("Cmd["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].cmd);
           Serial.print(F("port["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].port);
           Serial.print(F("action["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].action);
           Serial.print(F("action2["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].action2);
           Serial.print(F("action3["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].action3);
           Serial.print(F("action4["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].action4);
           Serial.print(F("action5["));Serial.print(i);Serial.print(F("]="));Serial.println(CmdQueue[i].action5);
        */
      }
    }
  }



  return (result);

}



//push_SendHttp(push_user, ardu_user, adru_pass, "launch_logger")
bool  ethclient_SendHttp(char *www_site, char *push_usr, char *arduino_name, char *arduino_pass, char *http_file, byte mode)
{
  if (!push_CheckPin()) {
    return 0;
  }

#if DEBUG_SERIAL_PUSH == 1
  Serial.println(F("http connecting.."));
#endif

  char *result = 0;


  if (_client.connect(www_site, 80)) {    //andruino.it as number
#if DEBUG_SERIAL_PUSH == 1
    Serial.println(F("connected"));
#endif
    ethbuff_ClientClear();                  //clear the TX buffer before use it
    ethbuff_ClientPrint(F("GET /iws4_arduino/"));
    ethbuff_ClientPrint(http_file);
    ethbuff_ClientPrint(F("?user="));
    ethbuff_ClientPrint(push_usr);
    ethbuff_ClientPrint(F("&pin="));
    ethbuff_ClientPrint(pin_push_flash);
    ethbuff_ClientPrint(F("&ardu="));
    ethbuff_ClientPrint(arduino_name);
    ethbuff_ClientPrint(F("&pass="));
    ethbuff_ClientPrint(arduino_pass);
    ethbuff_ClientPrint(F("&mode="));
    ethbuff_ClientPrint(mode);
    ethbuff_ClientFlush();

    // char ServerResponse[20];
    result = ethclient_FinishGetStream(eth_buffer, sizeof(eth_buffer), "NO ERR", TIMEOUT_CLIENT_CONNECTION, NO_KEEP_ALIVE);
  }
  else {
#if DEBUG_SERIAL_PUSH == 1
    Serial.println(F("result: FAIL"));
#endif
    ethbuff_delay_and_stop();
  }

  if (result) {
    push_success_cnt++;    //increment the counter of good push connection
    return true;
  }
  else {
    push_fail_cnt++;     //increment the counter of bad push connection
    return false;
  }

}


/*
  bufferino: AndruCMD: &cmd=System&port=2&action=5&action2=10&action3=12&action4=0&action5=&active=0
  key: &cmd=System&port=2&action=5&action2=10&action3=12&action4=0&action5=&active=0
  key int: 3079
  separator_ptr:&port=2&action=5&action2=10&action3=12&action4=0&action5=&active=0
  separator_ptr int: 3090
  lenght: 6
  out_buffer: System

*/

//#define DEBUG_SearchKeyGET
bool json_SearchKeyGET (char *bufferino, char *search_string, char *out_buffer, byte out_buffer_max_size,  char *separator_char ) {

  char *key;
  char *separator_ptr;
  char *new_pointer;
  byte search_string_lenght;
  char * start_pointer;
  int size_out_buffer;


  key = strstr(bufferino, search_string);

#ifdef DEBUG_SearchKeyGET
  Serial.print(F("bufferino: ")); Serial.println(bufferino);
  Serial.print(F("search for: ")); Serial.println(search_string);
  Serial.print(F("key: ")); Serial.println(key);
  Serial.print(F("key int: ")); Serial.println((int)key);
  Serial.print(F("out_buffer sizeof: ")); Serial.println(out_buffer_max_size);
#endif

  if (key) {
    search_string_lenght = strlen(search_string);
    separator_ptr  = strstr(key + 1, separator_char);       //find &

    if (separator_ptr == 0)
      separator_ptr  = strstr(key + 1, " ");       //find space to manage ..=0&action3=0 HTTP/1.1

    if (separator_ptr == 0)                                 //if no &, means that the http is ended
      separator_ptr  = key + strlen(key);                 //end buffer

    start_pointer = key + search_string_lenght;
    size_out_buffer = separator_ptr - key - search_string_lenght;

#ifdef DEBUG_SearchKeyGET
    Serial.print(F("\nseparator_ptr:"));
    Serial.println(separator_ptr);
    Serial.print(F("separator_ptr int: "));
    Serial.println((int)separator_ptr);
    Serial.print(F("start_pointer int: ")); Serial.println((int)start_pointer);
    Serial.print(F("size_out_buffer: ")); Serial.println((int)size_out_buffer);
#endif

    if (size_out_buffer < 0) {
      Serial.println(F("json_SearchKeyGET: ERRROR FORMAT"));
      return 0;
    }
    if (size_out_buffer > out_buffer_max_size) {
      Serial.println(F("json_SearchKeyGET: SIZE EXCEED"));
      // Serial.print(F("size buffer da scrivere:"));Serial.println(size_out_buffer);
      // Serial.print(F("size buffer:"));Serial.println(size);
      return 0;
    }

    memset(out_buffer, 0, out_buffer_max_size);
    strncat(out_buffer, start_pointer, size_out_buffer);
    out_buffer[size_out_buffer] = '\0';


#ifdef DEBUG_SearchKeyGET
    Serial.print(F("out_buffer: ")); Serial.println(out_buffer);
#endif
    return 1;
  } else
    return 0;
}
