/*
 * 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 client for rover-app to rover-web communication
 *
 * Contributors:
 *    M.Ozcelikors <mozcelikors@gmail.com>, created 26.10.2017
 *
 */

#include <tasks/socket_client_task.h>

#include <unistd.h>
#include <ctime>
#include <libraries/timing/timing.h>
#include <interfaces.h>
#include <pthread.h>

#include <unistd.h>
#include <string.h>

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

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

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

#include <math.h>

#include <roverapp.h>

/* Global definitions */
int roverapp_send_sockfd;

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

Json::Value constructJSONData (int data_type)
{
	Json::Value data;
	switch (data_type)
	{
		case SENSOR_DATA:
			data["rover_dtype"] = "sensor";
			data["data"]["infrared0"] = ceil(infrared_shared[0]);
			data["data"]["infrared1"] = ceil(infrared_shared[1]);
			data["data"]["infrared2"] = ceil(infrared_shared[2]);
			data["data"]["infrared3"] = ceil (infrared_shared[3]);
			data["data"]["front"] = ceil (distance_sr04_front_shared);
			data["data"]["rear"] = ceil (distance_sr04_back_shared);
			data["data"]["temperature"] = ceil (temperature_shared);
			data["data"]["humidity"] = ceil (humidity_shared);
			data["data"]["bearing"] = ceil (bearing_shared);
			break;
		case UTIL_DATA:
			data["rover_dtype"] = "util";
			data["data"]["core0"] = cpu_util_shared[0];
			data["data"]["core1"] = cpu_util_shared[1];
			data["data"]["core2"] = cpu_util_shared[2];
			data["data"]["core3"] = cpu_util_shared[3];
			break;
		default:
			data["rover_dtype"] = "none";
			break;
	}
	return data;
}

void Socket_Client_Task_Terminator (int dummy)
{
	close(roverapp_send_sockfd);
	running_flag = 0;
}

void *Socket_Client_Task (void * arg)
{
	timing socket_client_task_tmr;

	socket_client_task_tmr.setTaskID("Socket_Client_Task");
	socket_client_task_tmr.setDeadline(0.5);
	socket_client_task_tmr.setPeriod(0.5);

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

	/* Socket related initializations */
	int n;
	struct sockaddr_in serv_addr;
	struct hostent *server;
	char client_buffer[JSON_DATA_BUFSIZE];
	char * eof_str = "\r\n";
	int connected_flag = 0;

	/* Send these data each iteration*/
	int job_count = 2;
	int job_list[job_count] = {SENSOR_DATA, UTIL_DATA};
	int job_idx = 0;

	/* Create JSON object to hold sensor data */
	Json::FastWriter  string_writer;

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

		//Task content starts here -----------------------------------------------
		/* For Connecting / Reconnecting */
		if (checkClientSocketStatus(roverapp_send_sockfd)!=0)
		{
			connected_flag = 0;
		}

		if (connected_flag == 0)
		{
			/* Try to connect or reconnect */
			/* Create socket, and connect to the socket */
			close(roverapp_send_sockfd);
			roverapp_send_sockfd = socket(AF_INET, SOCK_STREAM, 0);
			if (roverapp_send_sockfd < 0)
				perror("ERROR opening socket");
			server = gethostbyname(CONNECTION_HOSTNAME);
			if (server == NULL) {
				fprintf(stderr,"ERROR, no such host\n");
				exit(0);
			}
			bzero((char *) &serv_addr, sizeof(serv_addr));
			serv_addr.sin_family = AF_INET;
			bcopy((char *)server->h_addr,
				 (char *)&serv_addr.sin_addr.s_addr,
				 server->h_length);
			serv_addr.sin_port = htons(ROVERAPP_SEND_PORT);

			/* Try to connect */
			if (connect(roverapp_send_sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) == 0)
			{
				connected_flag = 1;
				job_idx = 0;
			}
		}
		else
		{
			/* Connected, start writing */
			/* Construct the JSON data and Write to string */
			std::string temp = string_writer.write(constructJSONData(job_list[job_idx++]));
			if (job_idx == job_count)
				job_idx = 0;

			/* Clear buffer and Write to buffer from string */
			bzero(client_buffer, JSON_DATA_BUFSIZE);
			if (strncpy(client_buffer, temp.c_str(), sizeof(client_buffer)) == NULL)
			{
				perror("strcpy temp");
			}
			client_buffer[sizeof(client_buffer)-1] = 0;

			/* Attach end of file character to string*/
			if (strcat(client_buffer, eof_str) == NULL)
			{
				perror("strcat EOF");
			}

			/* Write to socket */
			if (write(roverapp_send_sockfd, client_buffer, strlen(client_buffer)) == -1)
			{
				perror("write");
				/* Very important approach to have re-usable socket client */
				/* Checking connection status by using exit status of 'write' */
				printf ("Disconnected from server : socket_client.cpp");
				connected_flag = 0;
			}
		}

		//Task content ends here -------------------------------------------------
		socket_client_task_tmr.recordEndTime();
		socket_client_task_tmr.calculateExecutionTime();
		socket_client_task_tmr.calculateDeadlineMissPercentage();
		socket_client_task_tmr.incrementTotalCycles();
		pthread_mutex_lock(&socket_client_task_ti_l);
			socket_client_task_ti.deadline = socket_client_task_tmr.getDeadline();
			socket_client_task_ti.deadline_miss_percentage = socket_client_task_tmr.getDeadlineMissPercentage();
			socket_client_task_ti.execution_time = socket_client_task_tmr.getExecutionTime();
			socket_client_task_ti.period = socket_client_task_tmr.getPeriod();
			socket_client_task_ti.prev_slack_time = socket_client_task_tmr.getPrevSlackTime();
			socket_client_task_ti.task_id = socket_client_task_tmr.getTaskID();
			socket_client_task_ti.start_time = socket_client_task_tmr.getStartTime();
			socket_client_task_ti.end_time = socket_client_task_tmr.getEndTime();
		pthread_mutex_unlock(&socket_client_task_ti_l);
		socket_client_task_tmr.sleepToMatchPeriod();
	}

	/* the function must return something - NULL will do */
	return NULL;
}



