#include "SBE41.hpp"
#include "mcuRealTimeClock.hpp"

SDLogger sdLogger = SDLogger::getInstance();
mcuRealTimeClock mcuRTC_SBE41 = mcuRealTimeClock::getInstance();

void usart6RXIdleCallback(UART_HandleTypeDef *huart);

bool commandIP = false;
int8_t SBE41::sendCommand(SBE41::SBE41Commands cmd, string &deQTimestamp, string &deQString, bool noWait)
{
	int8_t returnValue = 0;            	//<0 is an error, =0 is in process, >0 is success

	CommandParams cmdParams = CmdParam[cmd];
	
	string dateTimeString = "";
	char engrMsg[256] = "";
	
	uint8_t checkRandTResp = 0;

	if (!commandIP)
	{
		memset(usart6RXBuffer, 0, sizeof(usart6RXBuffer));
		deQString.clear();
		numTimeouts = 0;
		if (noWait)
		{
			HAL_UART_Transmit_IT(&hUSART6, cmdParams.cmdPtr, cmdParams.cmdSize);
		}
		else
		{
			HAL_UART_Receive_IT(&hUSART6, usart6RXBuffer, cmdParams.responseSize);
			HAL_UART_Transmit_IT(&hUSART6, cmdParams.cmdPtr, cmdParams.cmdSize);
		}
		
		memset(engrMsg, 0, sizeof(engrMsg));
		snprintf(engrMsg, sizeof(engrMsg), "%s\t%s\tSending command: %s", IDTag, mcuRTC_SBE41.getCPFTimestamp().c_str(), cmdParams.cmdLabel);
		sdLogger.logEngrMsg(engrMsg, sizeof(engrMsg));

		if (noWait)
		{
			commandIP = false;
			returnValue = 1;
		}
		else
		{
			commandIP = true;
			returnValue = 0;
		}
	}
	else
	{	
		returnValue = 1;
	}

	return returnValue;
}
 

extern "C" void USART6_IRQHandler()
{
	//cout << "hit LPUART1_IRQHandler" << endl;

	HAL_UART_IRQHandler(&hUSART6);

	if (__HAL_UART_GET_FLAG(&hUSART6, UART_FLAG_IDLE))
	{
		usart6RXIdleCallback(&hUSART6);
		__HAL_UART_CLEAR_IDLEFLAG(&hUSART6); 
	}
}

void usart6RXIdleCallback(UART_HandleTypeDef *huart)
{
	char engrMsg[256] = "";
	string sBuffer = (char*)usart6RXBuffer;

	//HAL_UART_DMAStop(&hUSART6);
	//TODO need to create a GPS message structure with timestamp, message, qCount?, message length?, etc.
//	msgQ.enqueue(mcuRTC.getCPFTimestamp(), uart7RXBuffer);
	
	//TODO this isn't actually logging the SBuffer which seems like a really awkward way to do this anyway
	snprintf(engrMsg, sizeof(engrMsg), "SBE41 RXIdleCallback rec'd: %s\t at time: %s", sBuffer.c_str(), mcuRTC_SBE41.getCPFTimestamp().c_str());
	sdLogger.logEngrMsg(engrMsg, sizeof(engrMsg));
	//cout << endl << "\t\thit HAL_UART_RXIdleCallback" << "   RX GPS Message: " << usart6RXBuffer;
}

//void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
//{
//	HAL_UART_DMAStop(&hUSART6);
//	//TODO need to create a GPS message structure with timestamp, message, qCount?, message length?, etc.
//	//msgQ.enqueue(mcuRTC.getCPFTimestamp(), uart7RXBuffer);
//	
//	cout << endl << "\t\tUART RX Complete Callback RX GPS Message: " << usart6RXBuffer;
//}
//
//void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
//{
//	cout << "\t\tUART RX Half Complete" << endl;
//}
//
//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
//{
//	cout << "\t\tUART TX Complete" << endl;
//}
//
//void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
//{
//	cout << "\t\tUART TX Half Complete" << endl;
//}


void SBE41::configUART6()
{
	GPIO_InitTypeDef GPIO_InitStruct;

	__HAL_RCC_USART6_CLK_ENABLE();
  	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	/**USART6 GPIO Configuration    
	PC6     ------> USART6_TX
	PC7     ------> USART6_RX 
	*/
	
	GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

	hUSART6.Instance        = USART6;
	hUSART6.Init.BaudRate   = 9600;
	hUSART6.Init.WordLength = UART_WORDLENGTH_8B;
	hUSART6.Init.StopBits   = UART_STOPBITS_1;
	hUSART6.Init.Parity     = UART_PARITY_NONE;
	hUSART6.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
	hUSART6.Init.Mode       = UART_MODE_TX_RX;
    
	if (HAL_UART_Init(&hUSART6) != HAL_OK)
	{
		cout << "Error in UART_Init" << endl;
		while (1) {}
	}
	
	NVIC_EnableIRQ(USART6_IRQn);
	__HAL_UART_ENABLE_IT(&hUSART6, UART_IT_IDLE);
}