/********************************* (C) РОТЕК ***********************************
 * @module  commands_api
 * @file    commands_api.c
 * @version 1.0.0
 * @date    XX.XX.XXXX
 * $brief   commands_api
 *******************************************************************************
 * @history     Version  Author         Comment
 * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
 *******************************************************************************
 */

#include "stm32f4xx.h"  
#include "commands_api.h"
#include "settings_api.h"
#include "sys_api.h"
#include "buttons.h"
#include "led.h"
#include "parameters.h"
#include "bt_6701_settings.h"
#include "bt_6701_commands.h"
#include "netconf.h"
#include "stm32f4x7_eth.h"
#include "http_server.h"
#include "config_service.h"
#include "rtc.h"

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

#include "lwip/opt.h"
#include "lwip/api.h"
#include "lwip/sys.h"


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


#define UDP_PORT 49049

TESTING_STATE_t TESTING_STATE = TEST_IDLE;

static TEST_t testState = TEST_WAIT;


bool ifTest_DEF = false;
bool ifTest_SET = false;
bool macWaiting = false;
bool macIsInstalled = false;
bool fUpdatable = false;
bool fDefPressed = false;

bool testEthernet = false;
bool testRtc = false;
bool testSerno = false;
bool testT2Ready = false;
bool testSet = false;

#define MSG_LEN   300
char msg[MSG_LEN];

extern char STM_ID[33];
extern char STM_ID_HEX[12];
uint8_t MAC[6];

/**
  * @brief  Общая структура настроек
  */
extern SETTINGS_t sSettings;

/**
  * @brief  
  */
void vTestCommands(void *params)
{

    for (;;)
    {
        if (fUpdatable) {

        	if(RTC_GetUnixTime() <= 946685800)
        	{
        		 memset(SETTINGS_GetTestState(), 0, 16);
        		 SETTINGS_SetTest(SETTINGS_GetTestState());
        		 LED_On(LED_MAJOR_R);
        		 //xTaskCreate(vTaskServiceLedBlinkErr, "LED_Blink_Err", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
        		 xTaskCreate(vTaskServiceLedBlink, "LED_Blink", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
        		 while(1){
        			 vTaskDelay(10);
        		 }
        	}
            //COM_TestEthernet();

        	SETTINGS_SetInfoDef();
            Test_Ethernet();
            vTaskDelay(8000);

            /* Стартует таск для опроса кнопки DEF */
            //xTaskCreate(vBootloaderButton, "DEF_Bootloader", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
            xTaskCreate(vTaskButtons, "DEF_Waiting", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
            xTaskCreate(vTaskServiceLedBlink, "LED_Blink", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
            
            while (!fDefPressed) {
            	vTaskDelay(10);
            }

            LED_On(LED_INIT_R);
            LED_On(LED_MAJOR_R);
            LED_On(LED_MINOR_R);

            //sSettings.bootParams.loadMode = 1;
            SetLoadMode();
            COM_TestSerno();

            COM_SetTestState(T2READY);
            vTaskDelay(1000);
            NVIC_SystemReset();

            while (1) {};
        }
      
        switch (testState)
        {
            case TEST_WAIT :
            break;
              
            case TEST_U232 :
                Test_U232();
            break;
#ifndef HARDWARE_BT6709
            case TEST_DRY :
                Test_DRY();
            break;
#endif
            case TEST_DEF :
                if (!ifTest_DEF) {
                    ifTest_DEF = true;
                    xTaskCreate(vTest_DEF, "DEF_Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
                }
            break;

            case TEST_SET :
            	if (!ifTest_SET) {
					ifTest_SET = true;
					xTaskCreate(vTest_SET, "SET_Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
				}
            break;

            case TEST_RTC :
            	COM_TestRtc();
            break;

            case TEST_SPIFLASH :
            	COM_TestSPIflash();
            break;

            case TEST_ETHERNET :
            	COM_SetMAC();
                Test_Ethernet();
            break;
            
            case TEST_SERNO :
                Test_Serno();
            break;
            
            
            default :
            break;
        }
        
        vTaskDelay(200);
      //TestProcessing();
    }
}

/**
  * @brief  
  */
void TEST_SetTest(TEST_t state)
{
    // Изменяем стейт только в том случае если контроллер находится в режиме ожидания
    if (testState == TEST_WAIT)
        testState = state;
    
    // На TEST_WAIT можно изменить всегда
    if (state == TEST_WAIT)
        testState = state;
}

/**
  * @brief  Считать статут тестирования (T0, T1, etc)
  */
void COM_ReadTestState(void)
{
  if (strncmp(SETTINGS_GetTestState(), "T0READY", 5) == 0) {
	TESTING_STATE = T0READY;
	printf("T0READY\r\n");
  }
  else if (strncmp(SETTINGS_GetTestState(), "T0OK", 5) == 0)
	TESTING_STATE = T0OK;
  else if (strncmp(SETTINGS_GetTestState(), "T1OK", 5) == 0) {
	TESTING_STATE = T1OK;
// TODO Если осуществлять поддержку старых версий UCN нужно учесть этот флаг
    fUpdatable = true;
  }
  else if (strncmp(SETTINGS_GetTestState(), "T2READY", 8) == 0) {
	TESTING_STATE = T2READY;
  }
  else
	TESTING_STATE = TEST_IDLE;
}

/**
  * @brief  Сохранение Serno и отправка сообщения на сервер
  */
void COM_TestSerno(void)
{
  struct netconn *conn;
  struct netbuf *buf;
  char *data;
  err_t err;
  char str[20] = {0};
  uint8_t len;

  /* Отправляем сообщение на сервер по UDP */
  memset(msg, 0, MSG_LEN);

  conn = netconn_new( NETCONN_UDP );

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

    if (err == ERR_OK)
    {
      netconn_connect(conn, IP_ADDR_BROADCAST, UDP_PORT);

      memset(str, 0, 20);
      GetModelStr(str, &len);
	  //strcpy(msg, sSettings.sSnmp.sysName);
      strcpy(msg, str);
	  strcat(msg, ";");

	  memset(str, 0, 20);
	  GetSerialNumberStr(str, &len);
	  //strcat(msg, sSettings.sInfo.serialNumber);
      strcat(msg, str);
	  strcat(msg, ";");

      /* empty column (format reqs)*/
      strcat(msg, ";");

	  strcat(msg, VERSION_TEST);
	  strcat(msg, ";");

      /* empty column (format reqs)*/
      strcat(msg, ";");
      /* empty column (format reqs)*/
      strcat(msg, ";");

      strcat(msg, STM_ID);

      strcat(msg, ";");
      /* empty column (format reqs)*/
      strcat(msg, ";");
      /* empty column (format reqs)*/
      strcat(msg, ";");

	  if (TESTING_STATE == T0OK)
	    strcat(msg, "T0OK");
	  else if (TESTING_STATE == T1OK)
	    strcat(msg, "T1OK");
	  else if (TESTING_STATE == T0READY)
	    strcat(msg, "T0READY");
	  else if (TESTING_STATE == T2READY)
	    strcat(msg, "T2READY");

	  strcat(msg, ";");
      /* empty column (format reqs)*/
      strcat(msg, ";");

	  buf = netbuf_new();
      data = netbuf_alloc(buf, strlen(msg));
      memcpy(data, msg, strlen(msg));
      netconn_send(conn, buf);
      netbuf_delete(buf);
	}
	else
      netconn_delete(conn);
  }
}

/**
  * @brief  Устанавливает mac адрес исходя из unique id
  */
void COM_SetMAC(void)
{
  uint8_t octet1 = 0;
  uint8_t octet2 = 0;
  uint8_t octet3 = 0;

  for (uint8_t i = 0; i < 4; i++)
  {
    octet1 ^= STM_ID_HEX[i];
	octet2 ^= STM_ID_HEX[i + 4];
	octet3 ^= STM_ID_HEX[i + 8];
  }

  /* Восьмой бит первого октета должен быть равен 0 */

/*  MAC[0] = octet1 & 0xFE;
  MAC[1] = octet2;
  MAC[2] = octet3;

  MAC[3] = 0x00;
  MAC[4] = 0x00;
  MAC[5] = 0x00;*/

  /* Устанавливаем MAC, но не сохраняем */
  snprintf(sSettings.sInfo.mac, MAC_LEN, "%02X-%02X-%02X-00-00-00", octet1 & 0xFE, octet2, octet3);

}

/**
  * @brief  Установить статут тестирования (T0, T1, etc)
  */
void COM_SetTestState(TESTING_STATE_t status)
{
  switch (status)
  {
    case T0READY :
	  //memset(sSettings.sFlags.testState, 0, 16);
	  //strncpy(sSettings.sFlags.testState, "T0READY", 7);
      memset(SETTINGS_GetTestState(), 0, 16);
	  strncpy(SETTINGS_GetTestState(), "T0READY", 7);
      TESTING_STATE = T0READY;
	break;

    case T0OK :
	  //memset(sSettings.sFlags.testState, 0, 16);
	  //strncpy(sSettings.sFlags.testState, "T0OK", 4);
      memset(SETTINGS_GetTestState(), 0, 16);
	  strncpy(SETTINGS_GetTestState(), "T0OK", 4);
      TESTING_STATE = T0OK;
	break;

	case T1OK :
	  //memset(sSettings.sFlags.testState, 0, 16);
	  //strncpy(sSettings.sFlags.testState, "T1OK", 4);
      memset(SETTINGS_GetTestState(), 0, 16);
	  strncpy(SETTINGS_GetTestState(), "T1OK", 4);
      TESTING_STATE = T1OK;
	break;

	case T2READY :
	  //memset(sSettings.sFlags.testState, 0, 16);
	  //strncpy(sSettings.sFlags.testState, "T2READY", 7);
      memset(SETTINGS_GetTestState(), 0, 16);
	  strncpy(SETTINGS_GetTestState(), "T2READY", 7);
      TESTING_STATE = T2READY;
	break;
  }

  SETTINGS_SetTest(SETTINGS_GetTestState());
}

/********************************* (C) РОТЕК **********************************/
