#include <stdio.h>
#include <ctype.h>
#include "stringops.h"
#include "resp.h"

static char io[1024];

int resp_add (resp_list *rl, char *l)
{
	resp *ret;

	#ifdef FUNCTIONS
	puts ("**resp_add");
	#endif

	ret = allocate (resp);

	while (isspace (*l)) l++;

	/******* lower bound *******/

	if (*l == '*')
	{
		ret->lowerflag = 0;
		ret->lower = 0;
	}
	else if (isdigit (*l) || (*l == '-') || (*l == '+'))
	{
		ret->lowerflag = 1;
		ret->lower = atoi(l);
	}
	else
	{
		free (ret);
		return 0;
	}

	while ((*l != '\0') && (*l != 'o')) l++;
	if (*l == '\0')
	{
		free (ret);
		return 0;
	}
	else
		l++;
	while (isspace (*l)) l++;

	/******* upper bound *******/

	if (*l == '*')
	{
		ret->upperflag = 0;
		ret->upper = 0;
	}
	else if (isdigit (*l) || (*l == '-') || (*l == '+'))
	{
		ret->upperflag = 1;
		ret->upper = atoi(l);
	}
	else
	{
		free (ret);
		return 0;
	}

	while ((*l != '\0') && (*l != ':')) l++;
	if (*l == '\0')
	{
		free (ret);
		return 0;
	}
	else
		l++;
	while (isspace (*l)) l++;

	/******* status change *******/

	if (isdigit (*l) || (*l == '-') || (*l == '+'))
	{
		ret->status_change = atoi(l);
	}
	else
	{
		free (ret);
		return 0;
	}

	while ((*l != '\0') && (*l != ':')) l++;
	if (*l == '\0')
	{
		free (ret);
		return 0;
	}
	else
		l++;
	while (isspace (*l)) l++;

	/******* priority *******/

	if (isdigit (*l) || (*l == '+'))
		ret->priority = atoi(l);
	else
	{
		free (ret);
		return 0;
	}

	while ((*l != '\0') && (*l != ':')) l++;
	if (*l == '\0')
	{
		free (ret);
		return 0;
	}
	else
		l++;
	while (isspace (*l)) l++;

	/******* response string *******/

	copystring (ret->response, l);

	if (rl->tail != NULL) rl->tail->next = ret;
	else rl->head = ret;
	rl->tail = ret;

	(rl->size)++;
	(rl->priority_total) += ret->priority;

	return 1;
}

static void resp_elements_burn (resp *r)
{
	#ifdef FUNCTIONS
	puts ("**resp_elements_burn");
	#endif

	if (r)
	{
		resp_elements_burn(r->next);

		free (r->response);
		free (r);
	}
}

void resp_burn (resp_list *r)
{
	#ifdef FUNCTIONS
	puts ("**resp_burn");
	#endif

	if (r != NULL)
	{
		resp_elements_burn (r->head);
		free (r);
	}
}

void resp_delete (resp_list *rl, resp *dead)
{
	resp *scan;

	#ifdef FUNCTIONS
	puts ("**resp_delete");
	#endif

	if ((rl == NULL) || (rl->head == NULL))
		return;

	if (rl->head == dead)
	{
		rl->head = dead->next;

		if (rl->head == NULL) rl->tail = NULL;

		(rl->priority_total) -= dead->priority;
		(rl->size)--;

		free (dead->response);
		free (dead);
	}
	else
	{
		for (scan = rl->head;
			(scan->next != NULL) && (scan->next != dead);
			scan = scan->next);
		
		if (scan->next != NULL)
		{
			if (scan->next == rl->tail) rl->tail = scan;
			scan->next = NULL;

			(rl->priority_total) -= dead->priority;
			(rl->size)--;

			free (dead->response);
			free (dead);
		}
	}
}

void resp_file_output (resp *r, FILE *f)
{
	char tempio[10];

	#ifdef FUNCTIONS
	puts ("**resp_file_output");
	#endif

	sprintf (io, "%+-4d", r->lower);
	sprintf (tempio, "%+-4d", r->upper);
	fprintf (f, "%s to %s:% -4d:% 4d:%s",
		r->lowerflag ? io : "****",
		r->upperflag ? tempio : "****",
		r->status_change, r->priority, r->response);
}

void resp_parse_output (char *l, char *name, globals *g)
{
	char *start, *end;
	#ifdef FUNCTIONS
	puts ("**resp_out_parse");
	#endif

	for (start = end = l; *end != '\0';)
	{
		char *tempstr;
		for (; (*end != '\0') && (*end != '/') && (*end != '%'); end++);

		tempstr = clip (start, end - 1);
		socket_write_noret (g->socket, tempstr);
		free (tempstr);

		switch (*end)
		{
			case '/':
				start = ++end;
			case '\0':
				socket_write (g->socket, "");
				break;
			case '%':
				switch (*(end + 1))
				{
					case 'p':
						socket_write_noret
							(g->socket, name);
						socket_write_noret
							(g->socket, "'");
						if (name[strlen (name) - 1] !=
							's')
							socket_write_noret
								(g->socket,
								"s");
						break;
					case 'o':
						socket_write_noret
							(g->socket, name);
						break;
					case '%':
						socket_write_noret
							(g->socket, "%");
						break;
					case 'r':
						if (g->room_current != NULL)
						{
							socket_write_noret
							(g->socket,
							g->room_current->name);
						}
						break;
					default:
						if ((*(end + 1) >= '0') &&
							(*(end + 1) <= '9'))
						{
							sleep (atoi (end +
								1));
						}
				}
				end++;
				start = ++end;
				break;
		}
	}
}

resp *resp_find_num (resp_list *rl, int n)
{
	resp *scan;

	#ifdef FUNCTIONS
	puts ("**resp_find_num");
	#endif

	for (scan = rl->head;
		(scan != NULL) && (n > 1);
		scan = scan->next, n--);
	return scan;
}

resp *resp_find_pri (resp_list *rl, int n)
{
	resp *scan;

	#ifdef FUNCTIONS
	puts ("**resp_find_pri");
	#endif

	for (scan = rl->head;
		(scan != NULL) && (n >= scan->priority);
		scan = scan->next, n -= scan->priority);
	return scan;
}