#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <time.h>

# include <math.h>

#include "sysfs.h"
#include "si.h"

struct si_watch_data {
	char			* d_object;
	char			* d_attr;
	double			d_secs;
	unsigned long		d_count;
	struct record_col	d_rc;
};


static const double default_secs = 3.0;
static const unsigned long default_count = 10;


/**
 *	watch_init - Check arguments and allocate private data structures.
 *	@a:	Session data.
 */

static int watch_init(struct si_action * a)
{
	struct si_watch_data * data;

	if (a->a_argc < 2 || a->a_argc > 4)
		return -EINVAL;

	data = calloc(1, sizeof(struct si_watch_data));
	if (!data)
		return -ENOMEM;

	data->d_secs = default_secs;
	data->d_count = default_count;

	switch (a->a_argc) { 
	case 4:
		data->d_count = strtoul(a->a_argv[3], NULL, 0);
	case 3:
		data->d_secs = strtod(a->a_argv[2], NULL);
	case 2:
		data->d_object = a->a_argv[0];
		data->d_attr = a->a_argv[1];
	default:
		break;
	}
	a->a_data = data;
	return 0;
}


static int watch_exec(struct si_action * a)
{
	struct si_watch_data * data = a->a_data;
	struct sysfs_object so;
	struct timespec req;
	double d_secs;
	char buffer[PAGE_SIZE];
	int error;
	int i;

	setvbuf(stdout, buffer, _IONBF, PAGE_SIZE);

	error = sysfs_object_init(&so, data->d_object);
	if (error)
		return error;

	req.tv_sec = (time_t)floor(data->d_secs);
	d_secs = data->d_secs;
	d_secs -= floor(data->d_secs);
	req.tv_nsec = (unsigned long)(d_secs * 1000000000.0); 
	
	dbg ("Watching %s / %s. Interval = %f, Count = %ld\n",
	     data->d_object, data->d_attr, data->d_secs, data->d_count);

	if (!data->d_count) {
		do {
			error = sysfs_read_file(data->d_attr, buffer);
			if (error < 0)
				goto Exit;
			error = 0;
			printf("%s\r", buffer);
			nanosleep(&req, NULL);
		} while(1);
	} else {
		for (i = 0; i < data->d_count; i++) {
			error = sysfs_read_file(data->d_attr, buffer);
			if (error < 0)
				goto Exit;
			error = 0;
			printf("%s\r", buffer);
			nanosleep(&req, NULL);
		}
	}
	printf("\n");
 Exit:
	sysfs_object_exit(&so);
	return error;
}

static void watch_exit(struct si_action * a)
{
	struct si_watch_data * data = a->a_data;

	a->a_data = NULL;
	free(data);
}

static const char * watch_help = "Monitor an attribute.";
static const char * watch_usage = "<object> <attribute> [ <seconds> [ <interval> ]";

decl_cmd(watch);

