/*
 * Copyright 2010, Intel Corporation
 *
 * This file is part of PowerTOP
 *
 * This program file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 * or just google for it.
 *
 * Authors:
 *	Arjan van de Ven <arjan@linux.intel.com>
 */
#include "display.h"
#include "lib.h"

#include <ncurses.h>


#include <vector>
#include <map>
#include <string>
#include <string.h>

using namespace std;

static int display = 0;

vector<string> tab_names;
map<string, class tab_window *> tab_windows;
map<string, string> tab_translations;

map<string, string> bottom_lines;

void create_tab(const string &name, const string &translation, class tab_window *w, string bottom_line)
{
	if (!w)
		w = new(class tab_window);

	w->win = newpad(1000,1000);
	tab_names.push_back(name);
	tab_windows[name] = w;
	tab_translations[name] = translation;
	bottom_lines[name] = bottom_line;
}


void init_display(void)
{
	initscr();
	start_color();

	cbreak(); /* character at a time input */
	noecho(); /* don't show the user input */
	keypad(stdscr, TRUE); /* enable cursor/etc keys */

	use_default_colors();

	create_tab("Overview", _("Overview"));
	create_tab("Idle stats", _("Idle stats"));
	create_tab("Frequency stats", _("Frequency stats"));
	create_tab("Device stats", _("Device stats"));

	display = 1;
}

void reset_display(void)
{
	if (!display)
		return;

	keypad(stdscr, FALSE);
	echo();
	nocbreak();

	resetterm();
}


WINDOW *tab_bar = NULL;
WINDOW *bottom_line = NULL;

static int current_tab;

void show_tab(unsigned int tab)
{
	class tab_window *win;
	unsigned int i;
	int tab_pos = 17;
	const char *c;

	if (!display)
		return;

	if (tab_bar) {
		delwin(tab_bar);
		tab_bar = NULL;
	}

	if (bottom_line) {
		delwin(bottom_line);
		bottom_line = NULL;
	}

	tab_bar = newwin(1, 0, 0, 0);

	wattrset(tab_bar, A_REVERSE);
	mvwprintw(tab_bar, 0,0, "%120s", "");
	mvwprintw(tab_bar, 0,0, "PowerTOP %s", PACKAGE_VERSION);

	bottom_line = newwin(1, 0, LINES-1, 0);
	wattrset(bottom_line, A_REVERSE);
	mvwprintw(bottom_line, 0,0, "%120s", "");

	c = bottom_lines[tab_names[tab]].c_str();
	if (c && strlen(c) > 0)
		mvwprintw(bottom_line, 0,0, c);
	else
		mvwprintw(bottom_line, 0, 0,
			"<ESC> %s | <TAB> / <Shift + TAB> %s | ", _("Exit"),
			_("Navigate"));


	current_tab = tab;

	for (i = 0; i < tab_names.size(); i++) {
			if (i == tab)
				wattrset(tab_bar, A_NORMAL);
			else
				wattrset(tab_bar, A_REVERSE);
			mvwprintw(tab_bar, 0, tab_pos, " %s ", tab_translations[tab_names[i]].c_str());

			tab_pos += 3 + tab_names[i].length();
	}

	wrefresh(tab_bar);
	wrefresh(bottom_line);

	win = tab_windows[tab_names[tab]];
	if (!win)
		return;

	prefresh(win->win, win->ypad_pos, win->xpad_pos, 1, 0, LINES - 3, COLS - 1);
}

WINDOW *get_ncurses_win(const char *name)
{
	class tab_window *w;
	WINDOW *win;

	w= tab_windows[name];
	if (!w)
		return NULL;

	win = w->win;

	return win;
}

WINDOW *get_ncurses_win(int nr)
{
	class tab_window *w;
	WINDOW *win;

	w= tab_windows[tab_names[nr]];
	if (!w)
		return NULL;

	win = w->win;

	return win;
}

WINDOW *get_ncurses_win(const string &name)
{
	return get_ncurses_win(name.c_str());
}

void show_prev_tab(void)
{
       class tab_window *w;

       if (!display)
               return;
       w = tab_windows[tab_names[current_tab]];
       if (w)
               w->hide();

       current_tab --;
       if (current_tab < 0)
               current_tab = tab_names.size() - 1;

       w = tab_windows[tab_names[current_tab]];
       if (w)
               w->expose();

       show_tab(current_tab);
}

void show_next_tab(void)
{
	class tab_window *w;

	if (!display)
		return;

	w = tab_windows[tab_names[current_tab]];
	if (w)
		w->hide();

	current_tab ++;
	if (current_tab >= (int)tab_names.size())
		current_tab = 0;

	w = tab_windows[tab_names[current_tab]];
	if (w)
		w->expose();

	show_tab(current_tab);
}

void show_cur_tab(void)
{
	if (!display)
		return;
	show_tab(current_tab);
}

void cursor_down(void)
{
	class tab_window *w;

	w = tab_windows[tab_names[current_tab]];
	if (w) {
		if (w->ypad_pos < 1000) {
			if (tab_names[current_tab] == "Tunables" || tab_names[current_tab] == "WakeUp") {
		                if ((w->cursor_pos + 7) >= LINES) { 
					prefresh(w->win, ++w->ypad_pos, w->xpad_pos, 
						1, 0, LINES - 3, COLS - 1);
				}			
					w->cursor_down(); 
			} else {
				prefresh(w->win, ++w->ypad_pos, w->xpad_pos, 
					1, 0, LINES - 3, COLS - 1);
			}
		}
	}

	show_cur_tab();
}

void cursor_up(void)
{
	class tab_window *w;

	w = tab_windows[tab_names[current_tab]];

	if (w) {
		w->cursor_up(); 
		if(w->ypad_pos > 0) {
			prefresh(w->win, --w->ypad_pos, w->xpad_pos,
				 1, 0, LINES - 3, COLS - 1);
		}
	}
	
	show_cur_tab();
}

void cursor_left(void)
{
        class tab_window *w;

	w = tab_windows[tab_names[current_tab]];
	
	if (w) {			
		if (w->xpad_pos > 0) {
			prefresh(w->win, w->ypad_pos,--w->xpad_pos, 
				1, 0, LINES - 3, COLS - 1);
		}
	}
}

void cursor_right(void) 
{
        class tab_window *w;

	w = tab_windows[tab_names[current_tab]];

	if (w) {
		if (w->xpad_pos < 1000) {
			prefresh(w->win, w->ypad_pos, ++w->xpad_pos, 
				1, 0, LINES - 3, COLS - 1);
		}
	}
}

void cursor_enter(void)
{
	class tab_window *w;

	w = tab_windows[tab_names[current_tab]];

	if (w) {
		w->cursor_enter();
		w->repaint();
	}
	show_cur_tab();
}

void window_refresh()
{
	class tab_window *w;

	w = tab_windows[tab_names[current_tab]];

	if (w) {
		w->ypad_pos = 0;
		w->xpad_pos = 0;
		w->window_refresh();
		w->repaint();
	}

	show_cur_tab();
}

int ncurses_initialized(void)
{
	if (display)
		return 1;
	return 0;
}
