/*
** SellaNMS
** $Id: modtest.cxx,v 2.4 2005/03/31 18:57:11 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <dlfcn.h>

#include "../../src/common/util.h"
#include "../../src/modules/module.h"
#include "../../src/modules/discovery/discovery.h"
#include "../../src/modules/storage/storage.h"
#include "../../src/modules/storage/storagedata.h"
#include "../../src/modules/configuration/configuration.h"

int main(int argc, char** argv) {
	int 	running = 0;
	Module* 	module_handle = NULL;
	char 	module_name[256];
	char	class_name[256];
	char	instance_function_name[256];
	char* 	error = NULL;
	Module*	module = NULL;
	Module* (*getInstance)(void) = NULL;

	if (argc == 1) {
		memset(module_name, 0, 256);	
	} else if (argc == 2) {
		strncpy(module_name, argv[1], 255);	
	} else {
		printf("Usage: modtest [module_name [class_name]]\n\n");
	}

       	initscr(); 
	cbreak(); 
	noecho();
        nonl();
        intrflush(stdscr, FALSE);
        keypad(stdscr, TRUE);

	running = 1;	
	while (running) {
		if (!isendwin()) {
			move(0,1);
			clrtoeol();
			mvaddstr(0, 1, "Options");
			if (!module_handle) {
				mvaddstr(1, 3, "1) Set Module Name");
				mvaddstr(2, 3, "2)    Load Module");
			} else {
				move(1, 1);
				clrtoeol();
				move(2, 1);
				clrtoeol();
			}
			if (!module && module_handle) {
				mvaddstr(3, 3, "3)       Call class constructor");
			} else {
				move(3, 1);
				clrtoeol();
			}
			if (module) {
				mvaddstr(4, 3, "4)          Start Module");
			} else {
				move(4, 1);
				clrtoeol();
			}
			if (module) {
				mvaddstr(5, 3, "5)       Call class destructor");
			} else {
				move(5, 1);
				clrtoeol();
			}
			if (!module && module_handle) {
				mvaddstr(6, 3, "6)    Unload Module");
			} else {
				move(6, 1);
				clrtoeol();
			}
			mvaddstr(8, 3, "C) Clear stdout");
			mvaddstr(9, 3, "V) View stdout");
			mvaddstr(10, 3, "R) Refresh Screen");
			mvaddstr(11, 3, "Q) Quit");
			mvaddstr(13, 1, "Current Module");
			mvaddstr(14, 3, module_name);
			mvaddstr(16, 1, "Messages");
			move (20, 1);
		}

		switch (getch()) {
			case '1':
				if (!module_handle) {
					move(17, 1);
					clrtoeol();
					move(18, 1);
					clrtoeol();

					mvaddstr(17, 3, "Enter module name: ");
					echo();
					getstr(module_name);
					noecho();

					for (char* c = module_name; *c; c++) {
						if (*c == '\n') {
							*c = 0;
						}
					}

					if (!strcmp(module_name, "")) {
						if (argc > 1) {
							strncpy(module_name, argv[1], 255);
	
							mvaddstr(17, 3, "No module name given:  Using ");
							addstr(module_name);
							addstr(".");
						}
					}
					move(14, 0);
					clrtoeol();
				} else {
					move(17, 1);
					clrtoeol();
					mvaddstr(17, 3, "Error: Module loaded.");
				}
				break;

			case '2':
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				if (module_handle) {
					mvaddstr(17, 3, "Error: Module already loaded.");
				} else {
					mvaddstr(17, 3, "Loading module: ");

					module_handle = (Module*) dlopen(module_name, RTLD_NOW);
					error = dlerror();
					if (error) {
						addstr("Failure( ");
						addstr(error);
						addstr(" ).");

						module_handle = NULL;
					} else {
						getInstance = (Module* (*)(void))dlsym(module_handle, "getInstance");
						error = dlerror();
						if (error) {
							addstr("Failure( ");
							addstr(error);
							addstr(" ).");

							dlclose(module_handle);
							module_handle = NULL;
							module = NULL;
						} else {
							addstr("Loaded.");
						}
					}
				}
				break;

			case '3':
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				if (!module_handle) {
					mvaddstr(17, 3, "Error: Module not loaded.");
				} else if (module) {
					mvaddstr(17, 3, "Error: Class already instanciated.");
				} else {
					mvaddstr(17, 3, "Calling constructor: ");

					endwin();	

					module = (*getInstance)();
					if (module) {
						addstr("Allocated.");
					} else {
						addstr("Failure.");
					}

					refresh();
				}
				break;

			case '4':
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				if (module) {
					mvaddstr(17, 3, "Staring module.");

					endwin();

					fprintf(stderr, " *** All Your Debug Are Belong To Us ***\n\n");

#if 0 
					ConfigNode* conf = new ConfigNode();
					module->issueCommand(COMMAND_MODULE_CONFIGURATION_READ, "/usr/users/sella/NetCrawler/etc/netcrawler.conf");
					module->issueCommand(COMMAND_MODULE_CONFIGURATION_GET, "bogus", conf);
#ifdef DEBUG
					conf->print();
#endif
#endif

#if 1
					StorageData* data = new StorageData();
					data->setFlag(STORAGEDATA_READ);
					data->setData("info.infoid", "");
					data->setData("info.name", "");
					module->issueCommand(COMMAND_MODULE_STORAGE_READ, data);
#ifdef DEBUG
					data->print();
#endif
					data->getTableCount();
					module->issueCommand(COMMAND_MODULE_STORAGE_WRITE, data);

#endif

#if 0
					module->issueCommand(COMMAND_MODULE_DISCOVERY_DISCOVER);
#endif

					fprintf(stderr, "\n *** End Debug ***\n\n");

					refresh();
					
				} else {
					move(17, 1);
					clrtoeol();
					mvaddstr(17, 3, "Error: No instance of module class.");
				}
				break;

			case '5':
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				if (module) {
					mvaddstr(17, 3, "Calling destructor: ");

					delete module;
					module = NULL;

					addstr("Done.");
				} else {
					move(17, 1);
					clrtoeol();
					mvaddstr(17, 3, "Error: No instance of module class.");
				}
				break;

			case '6':
				if (!module) {
					move(17, 1);
					clrtoeol();
					move(18, 1);
					clrtoeol();

					if(module_handle) {
						mvaddstr(17, 3, "Unloading: ");
	
						dlclose(module_handle);
						module_handle = NULL;

						addstr("Done.");
					} else {
						move(17, 1);
						clrtoeol();
						mvaddstr(17, 3, "Error: Module not loaded.");
					}
				} else {
					move(17, 1);
					clrtoeol();
					mvaddstr(17, 3, "Error: Class instance exists.");
				}
				break;

			case 'C':
			case 'c':
				endwin();	
				system("clear");
				refresh();
				break;

			case 'V':
			case 'v':
				if (isendwin()) {
					refresh();
				} else {
					endwin();	
				}
				break;

			case 'R':
			case 'r':
				clear();
				break;
	
			case 'Q':
			case 'q':
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				running = 0;
				break;			

			default:
				move(17, 1);
				clrtoeol();
				move(18, 1);
				clrtoeol();

				mvaddstr(17, 3, "Error: Invalid option.");
		}
	}			

	if (module) {
		delete module;
	}
	if (module_handle) {
		dlclose(module_handle);
	}

	endwin();
}
