/* jawsd - connects to AWS datalogger over serial connection and provides
 *         weather information to the network
 * Copyright (C) 2003-2004 Jeffrey Grafton <jgrafton@tjhsst.edu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>

#include "config.h"
#include "data_types.h"
#include "network_raw.h"

void *
socket_listen (void *voidptr)
{
	int listen_sock, comm_sock, size, yes = 1;
	struct sockaddr_in server_addr, client_addr;
	data_processed *processed = (data_processed *)voidptr;
	char formatted[1024];
	time_t current_time;
	
	syslog(LOG_INFO, "socket_listen: running.");
	
	if ((listen_sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
	{
		perror("socket");
		exit(1);
	}

	if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
	{
		perror("setsockopt");
		exit(1);
	}
	
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(NETWORK_RAW_TCP_PORT);
	server_addr.sin_addr.s_addr = INADDR_ANY; 
	memset(&(server_addr.sin_zero), '\0', 8);
	
	if (bind(listen_sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == -1)
	{
		perror("bind");
		exit(1);
	}
	
	if (setuid(UID) == -1)
	{
		perror("setuid");
	}
	else
	{
		printf("socket_listen dropped to uid %d\n", getuid());
	}

	if (listen(listen_sock, 5) == -1)
	{
		perror("listen");
		exit(1);
	}

	while (1)
	{
		size = sizeof(struct sockaddr_in);
		if ((comm_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &size)) == -1)
		{
			perror("accept");
			exit(1);
		}
		current_time = time(NULL);
		printf("%s: Connection from %s\n", ctime(&current_time), inet_ntoa(client_addr.sin_addr));

		syslog(LOG_INFO, "network_raw: Connection from %s on port %d", inet_ntoa(client_addr.sin_addr), NETWORK_RAW_TCP_PORT);
		
		size = format_data(processed, formatted, 1024);
		printf("Sent %d bytes\n", send(comm_sock, formatted, size, 0));
		close(comm_sock);
	}
	pthread_exit(0);
}

int
format_data (data_processed *data, char *string, int size)
{
	return snprintf(string, size, "%s\n	Current		Change		High	Time		Low	Time\nIndoor temp:	%gF		%gF		%gF	(%02hhd:%02hhd)		%gF 	(%02hhd:%02hhd)\nOutdoor temp:	%gF		%gF		%gF	(%02hhd:%02hhd)		%gF 	(%02hhd:%02hhd)\nAuxiliary temp:	%gF		%gF		%gF	(%02hhd:%02hhd)		%gF	(%02hhd:%02hhd)\n\n		Current		Change		High	Time		Low	Time\nHumidity:	%g%%		%g%%		%g%%	(%02hhd:%02hhd)		%g%%	(%02hhd:%02hhd)\nBarometer:	%g\"		%g\" 		%g\"	(%02hhd:%02hhd)		%g\"	(%02hhd:%02hhd)\nLight:		%g%%		%g%%		%g%%	(%02hhd:%02hhd)		%g%%	(%02hhd:%02hhd)\n\nWind:		%g mph %s (%g)\nAverage wind:	%g mph %s (%g)\nWind gust:	%g mph %s (%g) (%02hhd:%02hhd)\n\nRainfall rate: 	%g\"	High: %g\" (%02hhd:%02hhd)\nDaily rain: 	%g\"\nMonthly rain: 	%g\"\nYearly rain: 	%g\"\n\nCurrent wind chill:	%gF\nAverage wind chill:	%gF\nDew point:	%gF\n", 
	ctime(&data->datetime),
	data->indoor_temperature.current, data->indoor_temperature.rate, data->indoor_temperature.high, data->indoor_temperature.high_hour, data->indoor_temperature.high_minute, data->indoor_temperature.low, data->indoor_temperature.low_hour, data->indoor_temperature.low_minute,
	data->outdoor_temperature.current, data->outdoor_temperature.rate, data->outdoor_temperature.high, data->outdoor_temperature.high_hour, data->outdoor_temperature.high_minute, data->outdoor_temperature.low, data->outdoor_temperature.low_hour, data->outdoor_temperature.low_minute,
	data->auxiliary_temperature.current, data->auxiliary_temperature.rate, data->auxiliary_temperature.high, data->auxiliary_temperature.high_hour, data->auxiliary_temperature.high_minute, data->auxiliary_temperature.low, data->auxiliary_temperature.low_hour, data->auxiliary_temperature.low_minute,
	data->humidity.current, data->humidity.rate, data->humidity.high, data->humidity.high_hour, data->humidity.high_minute, data->humidity.low, data->humidity.low_hour, data->humidity.low_minute,
	data->barometer.current, data->barometer.rate, data->barometer.high, data->barometer.high_hour, data->barometer.high_minute, data->barometer.low, data->barometer.low_hour, data->barometer.low_minute,
	data->light.current, data->light.rate, data->light.high, data->light.high_hour, data->light.high_minute, data->light.low, data->light.low_hour, data->light.low_minute,
	data->wind.current_speed, data->wind.current_direction, data->wind.current_direction_degrees,
	data->wind.average_speed, data->wind.average_direction, data->wind.average_direction_degrees,
	data->wind.high_speed, data->wind.high_direction, data->wind.high_direction_degrees, data->wind.high_hour, data->wind.high_minute,
	data->rain.rate, data->rain.rate_high, data->rain.rate_high_hour, data->rain.rate_high_minute,
	data->rain.daily,
	data->rain.monthly,
	data->rain.yearly,
	data->wind.current_wind_chill,
	data->wind.average_wind_chill,
	data->dew_point
	);
}


