/*
 * 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", POWERTOP_SHORT_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 | ",_("Exit"));


	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") {
		                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) {
			if (tab_names[current_tab] == "Tunables") {
				prefresh(w->win, --w->ypad_pos, w->xpad_pos, 
					1, 0, LINES - 3, COLS - 1);
	                } else {
				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;
}
