/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2012 secunet Security Networks AG
 *
 * This program 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

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

#include <libpayload.h>
#include <coreboot_tables.h>

#include <curses.h>
#include <menu.h>
#include <form.h>

#ifndef HOSTED
#define HOSTED 0
#endif

static int min(int x, int y)
{
	if (x < y)
		return x;
	return y;
}

static int max(int x, int y)
{
	if (x > y)
		return x;
	return y;
}

void render_form(FORM *form)
{
	int y, x, line;
	WINDOW *w = form_win(form);
	WINDOW *inner_w = form_sub(form);
	int numlines = getmaxy(w)-2;
	getyx(inner_w, y, x);
	line = y - (y % numlines);
	WINDOW *der = derwin(w, getmaxy(w)-2, getmaxx(w)-2, 1, 1);
	wclear(der);
	wrefresh(der);
	delwin(der);
	copywin(inner_w, w, line, 0, 1, 1, min(numlines, getmaxy(inner_w)-line), 68, 0);
	wmove(w, y + 1 - line, x + 1);
	wrefresh(w);
}

int main()
{
	int ch, done;
	
	/* coreboot data structures */
	lib_get_sysinfo();

	struct cb_cmos_option_table *opttbl = get_system_option_table();

	if (opttbl == NULL) {
		printf("Could not find coreboot option table\n");
		halt();
	}

	/* prep CMOS layout into libcurses data structures */
	
	/* determine number of options, and maximum option name length */
	int numopts=0;
	int maxlength=0;
	struct cb_cmos_entries *option = first_cmos_entry(opttbl);
	while (option) {
		if ((option->config != 'r') && (strcmp("check_sum", option->name) != 0)) {
			maxlength = max(maxlength, strlen(option->name));
			numopts++;
		}
		option = next_cmos_entry(option);
	}
	if (numopts == 0) {
		printf("NO CMOS OPTIONS FOUND. EXITING!!!");
		return 1;
	}
	FIELD **fields = malloc(sizeof(FIELD*)*(2*numopts+1));
	int i;

	/* walk over options, fetch details */
	option = first_cmos_entry(opttbl);
	for (i=0;i<numopts;i++) {
		while ((option->config == 'r') || (strcmp("check_sum", option->name) == 0)) {
			option = next_cmos_entry(option);
		}
		fields[2*i] = new_field(1, strlen(option->name), i*2, 1, 0, 0);
		set_field_buffer(fields[2*i], 0, option->name);
		field_opts_off(fields[2*i], O_ACTIVE);

		fields[2*i+1] = new_field(1, 40, i*2, maxlength+2, 0, 0);
		char *buf = NULL;
		int fail = get_option_as_string(use_nvram, opttbl, &buf, option->name);
		switch (option->config) {
		case 'h': {
			set_field_type(fields[2*i+1], TYPE_INTEGER, 0, 0, (1<<option->length)-1);
			field_opts_on(fields[2*i+1], O_BLANK);
			break;
			  }
		case 's': {
			set_max_field(fields[2*i+1], option->length/8);
			field_opts_off(fields[2*i+1], O_STATIC);
			break;
			  }
		case 'e': {
			int numvals = 0;
			struct cb_cmos_enums *cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id);

			/* if invalid data in CMOS, set buf to first enum */
			if (fail && cmos_enum) {
				buf = cmos_enum->text;
			}

			while (cmos_enum) {
				numvals++;
				cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id);
			}

			char **values = malloc(sizeof(char*)*(numvals + 1));
			int cnt = 0;

			cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id);
			while (cmos_enum) {
				values[cnt] = cmos_enum->text;
				cnt++;
				cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id);
			}
			values[cnt] = NULL;
			field_opts_off(fields[2*i+1], O_EDIT);
			set_field_type(fields[2*i+1], TYPE_ENUM, values, 1, 1);
			free(values); // copied by set_field_type
			break;
			  }
		default:
			  break;
		}
		if (buf) set_field_buffer(fields[2*i+1], 0, buf);
#if HOSTED
// underline is non-trivial on VGA text
		set_field_back(fields[2*i+1], A_UNDERLINE);
#endif
		field_opts_off(fields[2*i+1], O_BLANK | O_AUTOSKIP | O_NULLOK);

		option = next_cmos_entry(option);
	}
	fields[2*numopts]=NULL;

	/* display initialization */
	initscr();
	keypad(stdscr, TRUE);
	cbreak();
	noecho();

	if (start_color()) {
		assume_default_colors (COLOR_BLUE, COLOR_CYAN);
	}
	leaveok(stdscr, TRUE);
	curs_set(1);

	erase();
	box(stdscr, 0, 0);
	mvaddstr(0, 2, "coreboot configuration utility");
	refresh();

	FORM *form = new_form(fields);
	int numlines = min(numopts*2, 16);
	WINDOW *w = newwin(numlines+2, 70, 2, 1);
	WINDOW *inner_w = newpad(numopts*2, 68);
	box(w, 0, 0);
	mvwaddstr(w, 0, 2, "Press F1 when done");
	set_form_win(form, w);
	set_form_sub(form, inner_w);
	post_form(form);

	done = 0;
	while(!done) {
		render_form(form);
		ch=getch();
		if (ch == ERR) continue;
		switch (ch) {
		case KEY_DOWN:
			form_driver(form, REQ_NEXT_FIELD);
			break;
		case KEY_UP:
			form_driver(form, REQ_PREV_FIELD);
			break;
		case KEY_LEFT:
			if (field_type(current_field(form)) == TYPE_ENUM) {
				form_driver(form, REQ_PREV_CHOICE);
			} else {
				form_driver(form, REQ_LEFT_CHAR);
			}
			break;
		case KEY_RIGHT:
			if (field_type(current_field(form)) == TYPE_ENUM) {
				form_driver(form, REQ_NEXT_CHOICE);
			} else {
				form_driver(form, REQ_RIGHT_CHAR);
			}
			break;
		case KEY_BACKSPACE:
		case '\b':
			form_driver(form, REQ_DEL_PREV);
			break;
		case KEY_DC:
			form_driver(form, REQ_DEL_CHAR);
			break;
		case KEY_F(1):
			done=1;
			break;
		default:
			form_driver(form, ch);
			break;
		}
	}

	endwin();

	for (i = 0; i < numopts; i++) {
		char *name = field_buffer(fields[2*i], 0);
		char *value = field_buffer(fields[2*i+1], 0);
		char *ptr;
		for (ptr = value + strlen (value) - 1;
		     ptr >= value && *ptr == ' '; ptr--);
		ptr[1] = '\0';
		set_option_from_string(use_nvram, opttbl, value, name);
	}

	unpost_form(form);
	free_form(form);

	/* TODO: reboot */
	halt();
}

