#include "post.h"
#include "cgi.h"
#include "ieee.h"
#include <string.h>

/* This program provides a CLI interface to the IEEE database functions
 * 
 *    It is probably best used for testing and debugging the functionality
 *    of the web interface.
 */

 void print_help(){
	printf("Command Summary:\n");
	printf(" help - prints help\n");
	printf(" insert key_pairs\n");
	printf("    type of insert figured out based on key pairs given\n");
	printf(" update key_pairs\n");
	printf("    updates table person with values from key pairs\n");
	printf(" view order order=number\n");
	printf(" total inv type=x sub_type=y color=z size=w\n");
	printf(" view expense \n");
	printf(" quit - quits\n");
	printf("Note:    Key_pairs is in the form of field1=val1 field2=val2 ...\n");
	printf("Example: insert inventory=1 type=tshirt color=red price=12.22\n");
 }


 /* Append and parse are intended to be used together. They parse
  *  key=value pairs and construct a QUERY_STRING from it
  */

 void append(char* append_string) {
	char buf[1024];
	if ( getenv ("QUERY_STRING") ) {
		strncpy(buf, getenv("QUERY_STRING"), 1023);
		strncat(buf, "&", 1024-strlen(buf));
		strncat(buf, append_string, 1024-strlen(buf));
		buf[1023]=0;
		setenv ("QUERY_STRING", buf, 1);
	} else
		setenv ("QUERY_STRING", append_string, 1);

 }

void parse(char* buf) {
	char *str1, *str2;
	str1=str2=buf;
	while (str2) {
		str1=strsep(&str2, " ");
		if (*str1)
			append(str1);
	}

	printf("Query String = '%s'\n",getenv("QUERY_STRING"));


}

/*
 * Strips the dot from a string in the form of $'xxxx.xx'
 *  gets string from keypairs using cgi library where
 *  key=variable_name
 */
int strip_dot(char* variable_name) {
	char  *str1, *str2;
	str2=get_data(variable_name);
	if (str2) { /* strips dot from $xxxxx.xx */
		str1=strsep(&str2, ".");
		strncat(str1, str2, 10);
	}
	return atoi(str1);
}

/*
 * The fill_* functions fill their respective structs with data from
 *            the QUERY_STRING environment variable (or POST).
 *
 *  fill_receipt - also associates a order_form with a list of receipts
 */
inventory_type* fill_inventory() {
	static inventory_type inventory;
	inventory.type=get_data("type");
	inventory.sub_type=get_data("sub_type");
	inventory.size=get_data("size");
	inventory.color=get_data("color");
	inventory.description=get_data("description");

	inventory.price=strip_dot("price");

	if (get_data("stock") )
		inventory.stock=atoi(get_data("stock"));
	else
		inventory.stock=0;

	return &inventory;
}

void fill_expense() {
	expense_type expense;

	if (!get_data("person")) {
		printf("Error: Expense insertion requires a person to be\n");
		printf("       associated with the expense.\n\n");
		return;
	}
	if (!get_data("amount")) {
		printf("Error: Expense insertion requires amount be specified\n");
		return;
	}

	expense.account=get_data("account");
	expense.amount=strip_dot("amount");
	expense.description=get_data("description");
	insert_expense(&expense, atoi(get_data("who")));
}

void fill_receipt() {
	receipt_type receipt;
	int order;

	if (!get_data("order")){
		/* create order form */
		order=1; /* <-- temporary solution */
	} else
		order=atoi(get_data("order"));

	if (!get_data("inventory")) {
		printf("Error: Receipt insertion requires a associated inventory\n");
		return ;
	} 

	if (get_data("tax")) 
		receipt.tax=atoi(get_data("tax"));
	else
		receipt.tax=0;

	receipt.price=strip_dot("price");
	receipt.description=get_data("description");
	receipt.account=get_data("account");
	insert_receipt(&receipt, order, atoi(get_data("inventory")));
}

persocom* fill_person() {
	static persocom person;
	if (get_data("ieee_number"))
		person.ieee_number=atoi(get_data("ieee_number"));
	else
		person.ieee_number=0;

	if (get_data("zip"))
		person.zip=atoi(get_data("zip"));
	else
		person.zip=0;

	if (get_data("phone"))
		person.phone=atoi(get_data("phone"));
	else
		person.phone=0;

	if (get_data("serial"))
		person.serial=atoi(get_data("serial"));
	else
		person.serial=0;

	person.url=get_data("url");
	person.real_name=get_data("real_name");
	person.user_name=get_data("user_name");
	person.password=get_data("password");
	person.email=get_data("email");
	person.street=get_data("street");
	person.city=get_data("city");
	person.description=get_data("description");

	return &person;

}

/* insert() checks QUERY_STRING for certain variables
 *    if they exist it calls other functions which 
 *    will attempt to add the anticapated data into
 *    their database.
 */   
void insert() {
	if (get_data("inventory")) 
		insert_inventory(fill_inventory());
	else if (get_data("expense")) 
		fill_expense();
	else if (get_data("receipt")) 
		fill_receipt();
	else if (get_data("person"))
		insert_person(fill_person());
	else
		printf("Please specify a table to insert into\n");
}

/*
 * From the CS180 example code
 */
void pretty_print(PGresult *res) {
	PQprintOpt print_opts;

	memset( &print_opts, '\0', sizeof( print_opts ));
	print_opts.header = 1;
	print_opts.align = 1;
	print_opts.html3 = 0;
	print_opts.fieldSep = "|";
	PQprint( stdout, res, &print_opts );

}

void view_order() {
	char buf[1024];

	if (!get_data("order")) {
		printf("Error: Missing serial for orderform query");
		return;
	}

	printf("\n====---- Items\n\n");

	sprintf(buf, "select inventory.type, inventory.sub_type, inventory.size, inventory.color, inventory.def_price from inventory, receipt where receipt.order_num=%s and receipt.item_num=inventory.entry_num",
		get_data("order"));
	pretty_print(exec(buf));

	printf("====---- Total\n\n");

	sprintf(buf, "select sum(inventory.def_price) from inventory, receipt where receipt.order_num=%s and receipt.item_num=inventory.entry_num",
		get_data("order"));
	pretty_print(exec(buf));

	printf("====---- Paid\n\n");
	sprintf(buf, "select paid from order_form where order_num=%s",
		get_data("order"));
	pretty_print(exec(buf));


}

void total_inventory(char *type, char *sub_type, char* size, char* color) {
	char buf[1024];
	sprintf(buf, "select count (*) as total from receipt where item_num IN (select entry_num from inventory where type='%s' and sub_type='%s' and size='%s' and color='%s') AND (select count (*) from order_form where paid=1 AND order_num=receipt.order_num) > 0",
		type, sub_type, size, color);
	pretty_print(exec(buf));
}

void total_inv() {
	total_inventory(get_data("type"), get_data("sub_type"), get_data("size"),
					get_data("color"));
}

void view_expense() {
	char buf[1024];
	sprintf(buf, "select amount, account, who, ds from expense");
	pretty_print(exec(buf));
}


int main() {
	char cmd[80], *cmd_ptr;
	setenv("NO_HEADERS", "TRUE", 1);
	printf("IEEE Databears Interface\n");
	printf("   type 'help' for help\n");

	while(1) {
		printf("> ");
		fgets(cmd, 75, stdin);
		setenv ("RESTART", "YES", 1);
		unsetenv ("QUERY_STRING");

		if ( strncasecmp(cmd, "help", 4) == 0 )
			print_help(); 

		else if ( strncasecmp(cmd, "insert", 6) == 0 ) {
			cmd_ptr=cmd+6;
			(char*)cmd_ptr=strsep(&cmd_ptr, "\n");
			parse(cmd_ptr);
			insert();
		} 

		else if ( strncasecmp(cmd, "update", 6) == 0 ) {
			cmd_ptr=cmd+6;
			(char*)cmd_ptr=strsep(&cmd_ptr, "\n");
			parse(cmd_ptr);
			update_person(fill_person());
		} 
		else if (strncasecmp(cmd, "view order", 10) == 0 ) {
			cmd_ptr=cmd+10;
			(char*)cmd_ptr=strsep(&cmd_ptr, "\n");
			parse(cmd_ptr);
			view_order();
		}
		else if (strncasecmp(cmd, "total inv ", 10) == 0 ) {
			cmd_ptr=cmd+10;
			(char*)cmd_ptr=strsep(&cmd_ptr, "\n");
			parse(cmd_ptr);
			total_inv();
		}
		else if (strncasecmp(cmd, "view expense", 12) == 0 ) {
			cmd_ptr=cmd+12;
			(char*)cmd_ptr=strsep(&cmd_ptr, "\n");
			parse(cmd_ptr);
			view_expense();
		}

		else if ( strncasecmp(cmd, "quit", 4) == 0)
			return(1); else
		printf("Invalid Command\n\n");




		fpurge(stdin);
	}

	return(0);
}
