/*
 * Copyright (c) 2017 FH Dortmund and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Description:
 *     Socket server for rover-web to rover-app communication
 *
 * Contributors:
 *    M.Ozcelikors <mozcelikors@gmail.com>, created 26.10.2017
 *
 */

#include <tasks/socket_server_task.h>

#include <string.h>
#include <ctime>
#include <wiringPi.h>
#include <unistd.h>
#include <libraries/timing/timing.h>
#include <api/basic_psys_rover.h>
#include <interfaces.h>
#include <pthread.h>
#include <softPwm.h>

#include <libraries/pthread_monitoring/collect_thread_name.h>
#include <roverapp.h>

/* Signal header */
#include <signal.h>

/* Socket defs header */
#include <socket_settings.h>

/* json-cpp library */
#include <json/json.h>

/* Global definitions */
int roverapp_listen_sockfd;
int newroverapp_listen_sockfd;

/* If returns nonzero -> socket has a non zero error status */
int checkServerSocketStatus (int socket_fd)
{
	//TODO: Fix this function!
	int error = 0;
	socklen_t len = sizeof (error);
	int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
	return error;
}

void parseJSONData (char *server_buffer)
{
	Json::Value root;
	Json::Reader reader;
	bool parsingSuccessful = reader.parse( server_buffer, root );
	if ( !parsingSuccessful )
	{
		std::cout  << "Failed to parse" << reader.getFormattedErrorMessages();
	}

	if (root["rover_dtype"].asString() == "control")
	{
		// Update shared variable
		pthread_mutex_lock(&keycommand_lock);
			//Take only the first char - since interface uses 1 char only
			keycommand_shared = root["data"]["command"].asString()[0];
			//printf("RECV=%c\n",keycommand_shared);
		pthread_mutex_unlock(&keycommand_lock);
	}
	else if (root["rover_dtype"].asString() == "speed")
	{
		// Update shared variable
		pthread_mutex_lock(&speed_lock);
			speed_shared = root["data"]["speed"].asInt();
			//printf("RECV=%d\n",speed_shared);
		pthread_mutex_unlock(&speed_lock);
	}
	else
	{
		std::cout << "Unable to parse in socket_server_task.cpp" << std::endl;
	}

}

void Socket_Server_Task_Terminator (int dummy)
{
	close(roverapp_listen_sockfd);
	close(newroverapp_listen_sockfd);
	running_flag = 0;
}

void *Socket_Server_Task(void * arg)
{
	timing socket_server_task_tmr;

	CollectThreadName("Socket_Server_Task");

	socket_server_task_tmr.setTaskID("Socket_Server_Task");
	socket_server_task_tmr.setDeadline(0.05);
	socket_server_task_tmr.setPeriod(0.05);

	/* Add termination signal handler to properly close socket */
	signal(SIGINT, Socket_Server_Task_Terminator);
	signal(SIGTERM, Socket_Server_Task_Terminator);
	signal(SIGKILL, Socket_Server_Task_Terminator);

	socklen_t clilen;
	char server_buffer[JSON_DATA_BUFSIZE];
	struct sockaddr_in serv_addr, cli_addr;
	int  n;
	int true_ = 1;
	int client_connected_flag = 0;

	/* First call to socket() function */
	roverapp_listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);

	if (roverapp_listen_sockfd < 0) {
		perror("ERROR opening socket");
		exit(1);
	}

	/* Handle re-binding problems */
	setsockopt(roverapp_listen_sockfd, SOL_SOCKET,SO_REUSEADDR,&true_,sizeof(int));

	/* Initialize socket structure */
	bzero((char *) &serv_addr, sizeof(serv_addr));

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(BINDING_HOSTNAME);
	serv_addr.sin_port = htons(ROVERAPP_LISTEN_PORT);
	memset(serv_addr.sin_zero, '\0', sizeof serv_addr.sin_zero);

	/* Now bind the host address using bind() call.*/
	if (bind(roverapp_listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
		perror("ERROR on binding");
		exit(1);
	}

	/* Now start listening for the clients, here process will
	  * go in sleep mode and will wait for the incoming connection
	*/
	listen(roverapp_listen_sockfd,5); // Max 5 connections queued
	clilen = sizeof(cli_addr);

	while(running_flag)
	{
		socket_server_task_tmr.recordStartTime();
		socket_server_task_tmr.calculatePreviousSlackTime();

		//Task content starts here -----------------------------------------------
		/* Handle client acception or re-acception */
		/* Checking if client socket is available */
		if (checkServerSocketStatus(newroverapp_listen_sockfd)!=0)
		{
			client_connected_flag = 0;
		}

		if (client_connected_flag == 0)
		{
			/* If no client is connected currently */
			/* Accept actual connection from the client */
			newroverapp_listen_sockfd = accept(roverapp_listen_sockfd, (struct sockaddr *)&cli_addr, &clilen);

			if (newroverapp_listen_sockfd < 0) {
				perror("ERROR on accept -> newroverapp_listen_sockfd");
				exit(1);
			}
			else
			{
				printf ("Client connected to newroverapp_listen_sockfd \n");
				client_connected_flag = 1;
			}
		}
		else
		{
			/* If a client is connected */
			/* If connection is established then start communicating */
			size_t buf_idx = 0;

			/* Read one char at a time until the EOF_STR "\r\n" is reached */
			while (buf_idx < JSON_DATA_BUFSIZE)
			{
				if ( 1 == read(newroverapp_listen_sockfd, &server_buffer[buf_idx], 1))
				{
					if (buf_idx > 0 &&  LINE_FEED == server_buffer[buf_idx] && CARRIAGE_RETURN == server_buffer[buf_idx - 1])
					{
						break;
					}
					buf_idx++;
				}
				else
				{
					/* Very important approach to have re-usable socket server */
					/* Client connection status is determined by exit status of read */
					printf ("Client disconnected!");
					client_connected_flag = 0;
					break;
				}

			}
			// Received buffer
			//printf ("buffer: %s\n",server_buffer);

			/* Remove \r\n from at the end of the string */
			server_buffer[buf_idx] = '\0';
			server_buffer[buf_idx-1] = '\0';

			/* Parse the JSON data, and update global variables */
			parseJSONData(server_buffer);
		}

		//Task content ends here -------------------------------------------------

		socket_server_task_tmr.recordEndTime();
		socket_server_task_tmr.calculateExecutionTime();
		socket_server_task_tmr.calculateDeadlineMissPercentage();
		socket_server_task_tmr.incrementTotalCycles();
		pthread_mutex_lock(&socket_server_task_ti_l);
			socket_server_task_ti.deadline = socket_server_task_tmr.getDeadline();
			socket_server_task_ti.deadline_miss_percentage = socket_server_task_tmr.getDeadlineMissPercentage();
			socket_server_task_ti.execution_time = socket_server_task_tmr.getExecutionTime();
			socket_server_task_ti.period = socket_server_task_tmr.getPeriod();
			socket_server_task_ti.prev_slack_time = socket_server_task_tmr.getPrevSlackTime();
			socket_server_task_ti.task_id = socket_server_task_tmr.getTaskID();
			socket_server_task_ti.start_time = socket_server_task_tmr.getStartTime();
			socket_server_task_ti.end_time = socket_server_task_tmr.getEndTime();
		pthread_mutex_unlock(&socket_server_task_ti_l);
		socket_server_task_tmr.sleepToMatchPeriod();

	}
}
