/*
 * udp_netsetting.c
 *
 *  Created on: 22.07.2016
 *      Author: balbekova
 */

#include "FreeRTOS.h"
#include "task.h"

#include "lwip/api.h"
#include "udp_netsetting.h"
#include "stm32_uid.h"
#include "parameters.h"
#include "netconf.h"
#include "web_params_api.h"
#include "main.h"
#include "hal.h"


#include <string.h>
#ifdef PRINTF_STDLIB
#include <stdio.h>
#endif
#ifdef PRINTF_CUSTOM
#include "tinystdio.h"
#endif

#undef DBG
#define DBG if(0)

#define RCV_TIMEOUT		1000
#define SEND_TIMEOUT    2000

#define DATA_BUF_LEN1   255

#define UDP_PORT 49049

char dataBuf1[DATA_BUF_LEN1];

static uint8_t udp_type_message = 0;  //0 - идентификационное сообщение; 1 - сообщение с настройками сети

void udp_message(char *buf)
{
	uint8_t len2 = 0;
	char str[97];

	memset(str, 0, 97);

	GetModelStr(str, &len2);
	strncat(buf, str, len2);
	strcat(buf, ";");

	GetSerialNumberStr(str, &len2);
	strncat(buf, str, len2);
	strcat(buf, ";");

	GetMacStr(str, &len2);
	strncat(buf, str, len2);
	strcat(buf, ";");

	GetVersionStr(str, &len2);
	strncat(buf, str, len2);
	strcat(buf, ";;;");

	memset(str, 0, 97);
	GetSTM32IDStr(str, &len2);
	strncat(buf, str, len2);
	strcat(buf, ";;;T2OK;;");
}

void udp_message_netSettings(char *buf)
{
  char str[100];
  uint8_t len;

  /* S/N */
  GetSerialNumberStr(str, &len);
  strcat(buf, "{\"serno\":\"");
  strncat(buf, str, len);

  /* WEB */
  GetDhcpStateUDP(str, &len);
  strcat(buf, "\",\"dhcp\":\"");
  strncat(buf, str, len);

  GetIpStr(str, &len);
  strcat(buf, "\",\"ipaddress\":\"");
  strncat(buf, str, len);

  GetGatewayStr(str, &len);
  strcat(buf, "\",\"gateway\":\"");
  strncat(buf, str, len);

  GetMaskStr(str, &len);
  strcat(buf, "\",\"mask\":\"");
  strncat(buf, str, len);

  strncat(buf, "\"}", 2);
}


uint8_t GetUDPParamValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen)
{
  char *beginValue = 0;
  char *endValue = 0;
  int  len = 0;
  char *strPtr = 0;

  strPtr = strstr(inStr, paramName);

  if (strPtr != 0)
  {
    beginValue = strpbrk(strPtr,":");
    endValue = strpbrk(strPtr,",");
    if (endValue == 0)
    {
      endValue = strpbrk(strPtr,"}");
      if (endValue == 0)
            endValue = strpbrk(strPtr," ");
    }
    len = endValue - beginValue - 3;
    strncpy(paramValue, beginValue + 2, len);
    *endValue = '0';
    *beginValue = '0';
	*paramLen = len;
	return 1;
  }
  else
  {
	*paramLen = 0;
	return 0;
  }
}

void udp_recieve_parser(char *buf, u16_t rcvlen)
{
  uint8_t valueLen = 0;
  uint8_t len2 = 0;
  const uint8_t len = 100;
  char value[100];
  char str[100];

  memset(str, 0, 100);

 // ClearParamString(buf);

  memset(value, 0, len);
  memset(str, 0, len);

  DBG buf[rcvlen]='\0';
  DBG printf("Rcvd (%d bytes): \t%s\r\n", rcvlen, buf);
  GetUDPParamValue(buf, "\"serno\"", value, &valueLen);
  if(valueLen != 0)
	  GetSerialNumberStr(str, &len2);
  else
	  return;

  if(strncmp(value, str, len2) == 0)
  {
	  memset(str, 0, len);

	  GetUDPParamValue(buf, "\"dhcp\"", str, &valueLen);

	 // memset(str, 0, len);
	  memset(value, 0, len);
	  GetUDPParamValue(buf, "\"ipaddress\"", value, &valueLen);
	  if(valueLen != 0)
	  {
		  SetUDPDhcpStateStr(str);
		  SetIPStr(value);
	  }
	  else{
		  udp_type_message = 1;
		  return;
	  }

	  if (strncmp(str, "True", 4) != 0)  // Если dhcp off устанавливаем параметры
	  {
		  memset(value, 0, len);

		  GetUDPParamValue(buf, "\"gateway\"", value, &valueLen);
		  if(valueLen != 0)
			  SetGatewayStr(value);
		  memset(value, 0, len);

		  GetUDPParamValue(buf, "\"mask\"", value, &valueLen);
		  if(valueLen != 0)
			  SetMaskStr(value);
		  memset(value, 0, len);
	  }
	  //else
		  //SetUDPDhcpStateStr(str);
	  // Если параметры WEB изменились выставляем флаг, сохраняем настройки и перезагружаемся
	 if (GetStateWebReinit() == true)
	  {
	//	_message_add_to_log("Изменение сетевых настр", "Инфо", "ND");
		 SetWebReinitFlag(false);
		SetConfirmWebParamsFlag();
		SaveWEBparam();
		HTTP_SaveSettings();

		Reboot();
	  }
  }
}



bool http_server_serve(struct netconn *conn)
{
    struct netbuf *inbuf;
    err_t res;
    char* buf;
    u16_t buflen;
    bool flag = false;

    netconn_set_recvtimeout(conn, RCV_TIMEOUT);
    res = netconn_recv(conn, &inbuf);

  //  DBG printf("recv failed %d\n", res);

    if (res == ERR_OK)
    {
        netbuf_data(inbuf, (void**)&buf, &buflen);
        udp_recieve_parser(buf, buflen);
        flag = true;
        netbuf_delete(inbuf);
    }

    /* TODO remove if tested */
    /* Close the connection (server closes in HTTP) */
    //netconn_close(conn);

    /* TODO remove if tested */
    /* Delete the buffer (netconn_recv gives us ownership,
    so we have to make sure to deallocate the buffer) */
    //netbuf_delete(inbuf);
    return flag;
}


void udp_netsettings_task(void *arg)
{
  struct netconn *udp_conn;
  struct netbuf *buf_snd;
  char *data_snd;
  err_t err;
  TickType_t timestamp = 0;
  uint32_t len;


  vTaskDelay(5000);

  udp_conn = netconn_new( NETCONN_UDP );

  if (udp_conn != NULL)
  {
    err = netconn_bind(udp_conn, IP_ADDR_ANY, UDP_PORT);

    if (err == ERR_OK)
    {

      for( ;; )
      {
    	netconn_connect(udp_conn, IP_ADDR_BROADCAST, UDP_PORT);
		memset(dataBuf1, 0, DATA_BUF_LEN1);

		switch(udp_type_message)
		{
		case 0:
		    if (timestamp + SEND_TIMEOUT < xTaskGetTickCount()) {
		        udp_message(dataBuf1);
		        timestamp = xTaskGetTickCount();
		    }
			break;
		case 1:
			udp_message_netSettings(dataBuf1);
			udp_type_message = 0;
			break;
		default:
			break;
		}

		len = strlen(dataBuf1);

        if (len > 0) {
            buf_snd = netbuf_new();
            data_snd = netbuf_alloc(buf_snd,len);
            memcpy(data_snd, dataBuf1, len);
            netconn_send(udp_conn, buf_snd);
            netbuf_delete(buf_snd);
            DBG printf("\r\nSent (%u bytes): \t%s\r\n", (unsigned int)len, dataBuf1);
        }

		netconn_disconnect(udp_conn);

		/* TODO remove if tested */
		//if(http_server_serve(udp_conn))
			 //vTaskDelay(1000);

		http_server_serve(udp_conn);
      }
    }
    else
    {
      netconn_delete(udp_conn);
      DBG printf("udp_netsettings_task: can't bind netconn\r\n");
    }
  }
  else
	  DBG printf("udp_netsettings_task: can't create new UDP netconn\r\n");

  for( ;; )
  {
	  vTaskDelay(10000);
  }

}

void UDP_netsetting_init() {
	xTaskCreate(udp_netsettings_task, ( char * ) "udp_netsettings_task", 4*configMINIMAL_STACK_SIZE , NULL, tskIDLE_PRIORITY, NULL);
}



