/*widget.c - Some usefull widgets*/

/*
 * (c) Stanislav Ievlev inger@linux.ru.net
 */

#include <curses.h>
#include <stdlib.h>
#include <string.h>

#include "rklogd-viewer.h"

extern WINDOW *win;
extern WINDOW *view_win;
extern WINDOW *top_win;

#define DIFF_LEN 3

WINDOW *
button_win (WINDOW * parent, int posx, int posy, char *text)
{
	int width = strlen (text) + 2;
	int height = 3;
	WINDOW *button_win =  derwin (parent, height, width, posx, posy);
	
	init_pair (7, COLOR_RED, COLOR_BLACK);
	wattrset (button_win, COLOR_PAIR (7));

	box (button_win, ACS_VLINE, ACS_HLINE);
	mvwaddstr (button_win, 1, 1, text);
	wrefresh (button_win);
	return (button_win);
}

void
select_button (WINDOW * select_win, char *text, int type)
{
	if (type)
	{
		wattrset (select_win, COLOR_PAIR (7) | A_BOLD);
	} else
	{
		wattrset (select_win, COLOR_PAIR (7));
	}

	box (select_win, ACS_VLINE, ACS_HLINE);
	mvwaddstr (select_win, 1, 1, text);

	wrefresh (select_win);
}

/*confirm box widget*/
int
confirm_win (char *head, char *text)
{
	WINDOW *tmp_win, *button_ok, *button_no;

	int     width = strlen (text) + DIFF_LEN * 2;
	int	height = 6;
	int     key = 0, res = 0;

	tmp_win =
		newwin (height, width, (LINES - height) / 2,
			(COLS - width) / 2);
	init_pair (6, COLOR_WHITE, COLOR_BLACK);

	wattrset (tmp_win, COLOR_PAIR (2));
	box (tmp_win, ACS_VLINE, ACS_HLINE);
	mvwaddstr (tmp_win, 0, (int) ((width - strlen (head)) / 2), head);
	wattrset (tmp_win, COLOR_PAIR (2) | A_BOLD);
	mvwaddstr (tmp_win, 1, (int) ((width - strlen (text)) / 2), text);

	button_ok = button_win (tmp_win, 2, DIFF_LEN, "  OK  ");
	button_no = button_win (tmp_win, 2,
			    (width - DIFF_LEN - strlen ("  NO  ") - 2),
			    "  NO  ");
	select_button (button_no, "  NO  ", 1);
	wrefresh (tmp_win);

	while (key != KEY_ENT)
	{
		key = getch ();
		switch (key)
		{
			case KEY_LEFT:
			case KEY_RIGHT:
			case KEY_UP:
			case KEY_DOWN:
			case KEY_NXT:
				if (res)
				{
					select_button (button_ok, "  OK  ",
						       0);
					select_button (button_no, "  NO  ",
						       1);
					res = 0;
				} else
				{
					select_button (button_no, "  NO  ",
						       0);
					select_button (button_ok, "  OK  ",
						       1);
					res = 1;
				}
				break;
			default:
				break;
		}

	}

	delwin (tmp_win);
	delwin (button_ok);
	delwin (button_no);

	redrawwin (win);
	return res;
}

void
menu_select (WINDOW * tmpwin, menu_item * items, int num, int type)
{
	if (type)
	{
		init_pair (8, COLOR_WHITE, COLOR_RED);
		wattrset (tmpwin, COLOR_PAIR (8) | A_BOLD);
		mvwaddstr (tmpwin, num, 1, items[num - 1].key);
		mvwaddstr (tmpwin, num, 3, items[num - 1].description);
	} else
	{
		wattrset (tmpwin, COLOR_PAIR (7) | A_BOLD);
		mvwaddstr (tmpwin, num, 1, items[num - 1].key);
		wattrset (tmpwin, COLOR_PAIR (7));
		mvwaddstr (tmpwin, num, 3, items[num - 1].description);
	}
	wrefresh (tmpwin);
}

/*menu widget*/
int
menu_win (menu_item * items, int nr_items, char *title, int posx, int posy)
{
	int     width = strlen (title) + 2 * DIFF_LEN + 3;
	int	height = nr_items + 2;
	int     selected = 1, key = -1;
	WINDOW	*tmp_win = newwin (height, width, posx, posy);

	init_pair (6, COLOR_WHITE, COLOR_BLACK);

	wattrset (tmp_win, COLOR_PAIR (2));
	box (tmp_win, ACS_VLINE, ACS_HLINE);

	mvwaddstr (tmp_win, 0, (int) ((width - strlen (title)) / 2), title);

	init_pair (7, COLOR_RED, COLOR_BLACK);
	for (selected = 0; selected < nr_items; selected++)
	{
		wattrset (tmp_win, COLOR_PAIR (7) | A_BOLD);
		mvwaddstr (tmp_win, selected + 1, 1, items[selected].key);
		wattrset (tmp_win, COLOR_PAIR (7));
		mvwaddstr (tmp_win, selected + 1, 3,
			   items[selected].description);
	}
	wrefresh (tmp_win);
	selected = 1;

	menu_select (tmp_win, items, selected, 1);
	while ((key != KEY_ENT) && (key != KEY_EXT))
	{
		key = getch ();
		menu_select (tmp_win, items, selected, 0);
		switch (key)
		{
			case KEY_UP:
				if (selected > 1)
					selected--;
				break;
			case KEY_DOWN:
				if (selected < nr_items)
					selected++;
				break;
			default:
				break;
		}
		menu_select (tmp_win, items, selected, 1);
	}

	delwin (tmp_win);

	redrawwin (win);
	wrefresh (win);

	redrawwin (view_win);
	wrefresh (view_win);

	redrawwin (top_win);
	wrefresh (top_win);

	if (key != KEY_EXT)
	{
		return (selected);
	} else
	{
		return -1;
	}
}

/*menu_select*/
void
top_menu_select (WINDOW * tmpwin, top_menu_item * items, int step, int num,
		 int type)
{
	if (type)
	{
		init_pair (8, COLOR_WHITE, COLOR_RED);
		wattrset (tmpwin, COLOR_PAIR (8) | A_BOLD);
		mvwaddstr (tmpwin, 0, step * num, items[num].description);
	} else
	{
		wattrset (tmpwin, COLOR_PAIR (7) | A_BOLD);
		mvwaddstr (tmpwin, 0, step * num, items[num].description);
	}
	wrefresh (tmpwin);

}

/*top menu widget*/
int
top_menu_win (top_menu_item * items, int nr_items)
{
	int     width = COLS;
	int	height = 1;
	int	step = (int) (COLS / nr_items);
	int     key = 0, selected = 0, do_exit = 1;
	WINDOW *tmp_win = newwin (height, width, 0, 0);

	init_pair (7, COLOR_RED, COLOR_BLACK);
	wattrset (tmp_win, COLOR_PAIR (7));

	/*draw items */
	width = 0;
	for (selected = 0; selected < nr_items; selected++)
	{
		mvwaddstr (tmp_win, 0, width, items[selected].description);
		width += step;
	}
	wrefresh (tmp_win);

	selected = 0;

	top_menu_select (tmp_win, items, step, selected, 1);

	while (do_exit)
	{
		key = getch ();
		top_menu_select (tmp_win, items, step, selected, 0);
		switch (key)
		{
			case KEY_LEFT:
			case KEY_UP:
				if (selected > 0)
				{
					selected--;
				} else
				{
					selected = nr_items - 1;
				};
				break;
			case KEY_RIGHT:
			case KEY_DOWN:
				if (selected < (nr_items - 1))
				{
					selected++;
				} else
				{
					selected = 0;
				};
				break;
			case KEY_EXT:
				do_exit = 0;
				break;
				/*work */
			case KEY_ENT:
				items[selected].menu_fun (1, step * selected);
				do_exit = 0;
				break;

			default:
				break;
		}
		top_menu_select (tmp_win, items, step, selected, 1);
	}

	delwin (tmp_win);

	redrawwin (stdscr);
	refresh ();

	redrawwin (top_win);
	wrefresh (top_win);

	redrawwin (view_win);
	wrefresh (view_win);

	redrawwin (win);
	wrefresh (win);

	return (selected);

}

void
inform_win (char *head, char *text, char *buttontext)
{
	WINDOW *tmp_win, *button_inf;

	int width = ((strlen (text) >
		  strlen (head)) ? strlen (text) : strlen (head)) +
		DIFF_LEN * 2;
	int height = 8;
	int key = 0;

	tmp_win =
		newwin (height, width, (LINES - height) / 2,
			(COLS - width) / 2);
	init_pair (6, COLOR_WHITE, COLOR_BLACK);

	wattrset (tmp_win, COLOR_PAIR (2));
	box (tmp_win, ACS_VLINE, ACS_HLINE);
	mvwaddstr (tmp_win, 0, (int) ((width - strlen (head)) / 2), head);

	wattrset (tmp_win, COLOR_PAIR (2) | A_BOLD);
	mvwaddstr (tmp_win, 2, (int) ((width - strlen (text)) / 2), text);

	button_inf =
		button_win (tmp_win, 4,
			    (int) ((width - strlen (buttontext)) / 2 - 1),
			    buttontext);
	select_button (button_inf, buttontext, 1);

	wrefresh (tmp_win);

	nonl ();
	noecho ();

	while (key != KEY_ENT)
		key = getch ();

	delwin (tmp_win);
	delwin (button_inf);

	redrawwin (win);
	wrefresh (win);
}

/*one line enter widget*/
char   *
enterline_win (char *head, char *value_name, char *old_value)
{
	char   *tmpstr = malloc (MAX_LINE);
	int     str_pointer = 0;

	WINDOW *tmp_win;

	int     width, height = 6;
	int     key = 0;

	if (old_value == NULL)
	{
		width = 20 + 2 * DIFF_LEN + strlen (value_name);
	} else
	{
		width = 20 + strlen (old_value) + 2 * DIFF_LEN +
			strlen (value_name);
	}

	tmp_win =
		newwin (height, width, (LINES - height) / 2,
			(COLS - width) / 2);
	init_pair (6, COLOR_WHITE, COLOR_BLACK);

	wattrset (tmp_win, COLOR_PAIR (2));
	box (tmp_win, ACS_VLINE, ACS_HLINE);
	mvwaddstr (tmp_win, 0, (int) ((width - strlen (head)) / 2), head);

	wattrset (tmp_win, COLOR_PAIR (2) | A_BOLD);

	snprintf (tmpstr, MAX_LINE, "Current %s:%s", value_name, old_value);
	mvwaddstr (tmp_win, 2, 1, tmpstr);
	memset (tmpstr, 0, MAX_LINE - 2);

	snprintf (tmpstr, MAX_LINE, "New %s:", value_name);
	mvwaddstr (tmp_win, 3, 1, tmpstr);
	memset (tmpstr, 0, MAX_LINE - 2);

	wrefresh (tmp_win);

	wattrset (tmp_win, COLOR_PAIR (2));

	nonl ();
	noecho ();

	/*view string */
	while ((key != KEY_ENT) && (key != KEY_EXT)
	       && (str_pointer < MAX_LINE))
	{
		key = getch ();
		if (key != KEY_BACKSPACE)
		{
			tmpstr[str_pointer++] = key;
			mvwaddch (tmp_win, 3,
				  5 + strlen (value_name) + str_pointer, key);
		} else
		{
			if (str_pointer > 0)
				mvwaddch (tmp_win, 3,
					  5 + strlen (value_name) +
					  (str_pointer--), ' ');
		}
		wrefresh (tmp_win);
	}

	tmpstr[--str_pointer] = 0;

	delwin (tmp_win);

	redrawwin (win);
	wrefresh (win);
	if (key != KEY_EXT)
	{
		return (tmpstr);
	} else
	{
		return old_value;
	}
}

/*menu with check boxes   -- on/off switches*/
void
check_menu_win (menu_item * items, int nr_items, char *title, int posx,
		int posy)
{

	int	width = strlen (title) + 2 * DIFF_LEN + 3;
	int	height = nr_items + 2;
	int     selected = 0, key = -1;
	WINDOW	*tmp_win = newwin (height, width, posx, posy);
	
	init_pair (6, COLOR_WHITE, COLOR_BLACK);

	wattrset (tmp_win, COLOR_PAIR (2));
	box (tmp_win, ACS_VLINE, ACS_HLINE);

	mvwaddstr (tmp_win, 0, (int) ((width - strlen (title)) / 2), title);

	init_pair (7, COLOR_RED, COLOR_BLACK);
	for (selected = 0; selected < nr_items; selected++)
	{
		wattrset (tmp_win, COLOR_PAIR (7) | A_BOLD);
		mvwaddstr (tmp_win, selected + 1, 1, items[selected].key);
		wattrset (tmp_win, COLOR_PAIR (7));
		mvwaddstr (tmp_win, selected + 1, 3,
			   items[selected].description);
	}
	wrefresh (tmp_win);
	selected = 0;

	(void) getch ();

	menu_select (tmp_win, items, selected, 1);

	while ((key != KEY_ENT) && (key != KEY_EXT))
	{
		key = getch ();
		menu_select (tmp_win, items, selected, 0);
		switch (key)
		{
			case KEY_UP:
				if (selected > 1)
					selected--;
				break;
			case KEY_DOWN:
				if (selected < nr_items)
					selected++;
				break;
			default:
				break;
		}
		menu_select (tmp_win, items, selected, 1);
		/*switch item on/off */
		if (key == ' ')
		{
			if (strchr (items[selected - 1].key, '*') != NULL)
			{
				strcpy (items[selected - 1].key, " ");
			} else
			{
				strcpy (items[selected - 1].key, "*");
			}
			menu_select (tmp_win, items, selected, 1);
		}		//if
	}			//while

	delwin (tmp_win);

	redrawwin (win);
	wrefresh (win);

	redrawwin (view_win);
	wrefresh (view_win);

	redrawwin (top_win);
	wrefresh (top_win);

	return;
}
