/*
 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * 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; either version 2 of the
 * License, or any later version.
 *
 * 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 Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <curses.h>
#include <ipxe/console.h>
#include <ipxe/settings.h>
#include <ipxe/editbox.h>
#include <ipxe/keys.h>
#include <ipxe/ansicol.h>
#include <ipxe/jumpscroll.h>
#include <ipxe/settings_ui.h>
#include <config/branding.h>

/** @file
 *
 * Option configuration console
 *
 */

/* Screen layout */
#define TITLE_ROW		1U
#define SETTINGS_LIST_ROW	3U
#define SETTINGS_LIST_COL	1U
#define SETTINGS_LIST_ROWS	( LINES - 6U - SETTINGS_LIST_ROW )
#define INFO_ROW		( LINES - 5U )
#define ALERT_ROW		( LINES - 2U )
#define INSTRUCTION_ROW		( LINES - 2U )
#define INSTRUCTION_PAD "     "

/** Layout of text within a setting row */
#define SETTING_ROW_TEXT( cols ) struct {				\
	char start[0];							\
	char pad1[1];							\
	union {								\
		struct {						\
			char name[ cols - 1 - 1 - 1 - 1 - 1 ];		\
			char pad2[1];					\
		} __attribute__ (( packed )) settings;			\
		struct {						\
			char name[15];					\
			char pad2[1];					\
			char value[ cols - 1 - 15 - 1 - 1 - 1 - 1 ];	\
		} __attribute__ (( packed )) setting;			\
	} u;								\
	char pad3[1];							\
	char nul;							\
} __attribute__ (( packed ))

/** A settings user interface row */
struct settings_ui_row {
	/** Target configuration settings block
	 *
	 * Valid only for rows that lead to new settings blocks.
	 */
	struct settings *settings;
	/** Configuration setting origin
	 *
	 * Valid only for rows that represent individual settings.
	 */
	struct settings *origin;
	/** Configuration setting
	 *
	 * Valid only for rows that represent individual settings.
	 */
	struct setting setting;
	/** Screen row */
	unsigned int row;
	/** Edit box widget used for editing setting */
	struct edit_box editbox;
	/** Editing in progress flag */
	int editing;
	/** Dynamically allocated buffer for setting's value */
	char *buf;
};

/** A settings user interface */
struct settings_ui {
	/** Settings block */
	struct settings *settings;
	/** Jump scroller */
	struct jump_scroller scroll;
	/** Current row */
	struct settings_ui_row row;
	/** Widget set used for editing setting */
	struct widgets widgets;
};

/**
 * Select a setting
 *
 * @v ui		Settings user interface
 * @v index		Index of setting row
 * @ret count		Number of setting rows
 */
static unsigned int select_setting_row ( struct settings_ui *ui,
					 unsigned int index ) {
	SETTING_ROW_TEXT ( COLS ) *text;
	struct settings *settings;
	struct setting *setting;
	struct setting *previous = NULL;
	unsigned int count = 0;

	/* Free any previous setting value */
	free ( ui->row.buf );
	ui->row.buf = NULL;

	/* Initialise structure */
	memset ( &ui->row, 0, sizeof ( ui->row ) );
	ui->row.row = ( SETTINGS_LIST_ROW + index - ui->scroll.first );

	/* Include parent settings block, if applicable */
	if ( ui->settings->parent && ( count++ == index ) )
		ui->row.settings = ui->settings->parent;

	/* Include any child settings blocks, if applicable */
	list_for_each_entry ( settings, &ui->settings->children, siblings ) {
		if ( count++ == index )
			ui->row.settings = settings;
	}

	/* Include any applicable settings */
	for_each_table_entry ( setting, SETTINGS ) {

		/* Skip inapplicable settings */
		if ( ! setting_applies ( ui->settings, setting ) )
			continue;

		/* Skip duplicate settings */
		if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
			continue;
		previous = setting;

		/* Read current setting value and origin */
		if ( count++ == index ) {
			fetchf_setting_copy ( ui->settings, setting,
					      &ui->row.origin,
					      &ui->row.setting, &ui->row.buf );
		}
	}

	/* Initialise edit box */
	memset ( &ui->row.editbox, 0, sizeof ( ui->row.editbox ) );
	init_editbox ( &ui->row.editbox, ui->row.row,
		       ( SETTINGS_LIST_COL +
			 offsetof ( typeof ( *text ), u.setting.value ) ),
		       sizeof ( text->u.setting.value ), 0, &ui->row.buf );

	return count;
}

/**
 * Copy string without NUL termination
 *
 * @v dest		Destination
 * @v src		Source
 * @v len		Maximum length of destination
 * @ret len		Length of (unterminated) string
 */
static size_t string_copy ( char *dest, const char *src, size_t len ) {
	size_t src_len;

	src_len = strlen ( src );
	if ( len > src_len )
		len = src_len;
	memcpy ( dest, src, len );
	return len;
}

/**
 * Draw setting row
 *
 * @v ui		Settings UI
 */
static void draw_setting_row ( struct settings_ui *ui ) {
	SETTING_ROW_TEXT ( COLS ) text;
	unsigned int curs_offset;
	const char *value;

	/* Fill row with spaces */
	memset ( &text, ' ', sizeof ( text ) );
	text.nul = '\0';

	/* Construct row content */
	if ( ui->row.settings ) {

		/* Construct space-padded name */
		value = ( ( ui->row.settings == ui->settings->parent ) ?
			  ".." : ui->row.settings->name );
		curs_offset = string_copy ( text.u.settings.name, value,
					    sizeof ( text.u.settings.name ) );
		text.u.settings.name[curs_offset] = '/';
		curs_offset += offsetof ( typeof ( text ), u.settings );

	} else {

		/* Construct dot-padded name */
		memset ( text.u.setting.name, '.',
			 sizeof ( text.u.setting.name ) );
		string_copy ( text.u.setting.name, ui->row.setting.name,
			      sizeof ( text.u.setting.name ) );

		/* Construct space-padded value */
		value = ui->row.buf;
		if ( ! ( value && value[0] ) )
			value = "<not specified>";
		curs_offset = string_copy ( text.u.setting.value, value,
					    sizeof ( text.u.setting.value ) );
		curs_offset += offsetof ( typeof ( text ), u.setting.value );
	}

	/* Print row */
	if ( ( ui->row.origin == ui->settings ) || ( ui->row.settings != NULL ))
		attron ( A_BOLD );
	mvprintw ( ui->row.row, SETTINGS_LIST_COL, "%s", text.start );
	attroff ( A_BOLD );
	move ( ui->row.row, ( SETTINGS_LIST_COL + curs_offset ) );
}

/**
 * Edit setting ui
 *
 * @v ui		Settings UI
 * @v key		Key pressed by user
 * @ret key		Key returned to application, or zero
 */
static int edit_setting ( struct settings_ui *ui, int key ) {
	assert ( ui->row.setting.name != NULL );
	ui->row.editing = 1;
	return edit_widget ( &ui->row.editbox.widget, key );
}

/**
 * Save setting ui value back to configuration settings
 *
 * @v ui		Settings UI
 */
static int save_setting ( struct settings_ui *ui ) {
	assert ( ui->row.setting.name != NULL );
	return storef_setting ( ui->settings, &ui->row.setting, ui->row.buf );
}

/**
 * Print message centred on specified row
 *
 * @v row		Row
 * @v fmt		printf() format string
 * @v args		printf() argument list
 */
static void vmsg ( unsigned int row, const char *fmt, va_list args ) {
	char buf[COLS];
	size_t len;

	len = vsnprintf ( buf, sizeof ( buf ), fmt, args );
	mvprintw ( row, ( ( COLS - len ) / 2 ), "%s", buf );
}

/**
 * Print message centred on specified row
 *
 * @v row		Row
 * @v fmt		printf() format string
 * @v ..		printf() arguments
 */
static void msg ( unsigned int row, const char *fmt, ... ) {
	va_list args;

	va_start ( args, fmt );
	vmsg ( row, fmt, args );
	va_end ( args );
}

/**
 * Clear message on specified row
 *
 * @v row		Row
 */
static void clearmsg ( unsigned int row ) {
	move ( row, 0 );
	clrtoeol();
}

/**
 * Print alert message
 *
 * @v fmt		printf() format string
 * @v args		printf() argument list
 */
static void valert ( const char *fmt, va_list args ) {
	clearmsg ( ALERT_ROW );
	color_set ( CPAIR_ALERT, NULL );
	vmsg ( ALERT_ROW, fmt, args );
	sleep ( 2 );
	color_set ( CPAIR_NORMAL, NULL );
	clearmsg ( ALERT_ROW );
}

/**
 * Print alert message
 *
 * @v fmt		printf() format string
 * @v ...		printf() arguments
 */
static void alert ( const char *fmt, ... ) {
	va_list args;

	va_start ( args, fmt );
	valert ( fmt, args );
	va_end ( args );
}

/**
 * Draw title row
 *
 * @v ui		Settings UI
 */
static void draw_title_row ( struct settings_ui *ui ) {
	const char *name;

	clearmsg ( TITLE_ROW );
	name = settings_name ( ui->settings );
	attron ( A_BOLD );
	msg ( TITLE_ROW, PRODUCT_SHORT_NAME " configuration settings%s%s",
	      ( name[0] ? " - " : "" ), name );
	attroff ( A_BOLD );
}

/**
 * Draw information row
 *
 * @v ui		Settings UI
 */
static void draw_info_row ( struct settings_ui *ui ) {
	char buf[32];

	/* Draw nothing unless this row represents a setting */
	clearmsg ( INFO_ROW );
	clearmsg ( INFO_ROW + 1 );
	if ( ! ui->row.setting.name )
		return;

	/* Determine a suitable setting name */
	setting_name ( ( ui->row.origin ?
			 ui->row.origin : ui->settings ),
		       &ui->row.setting, buf, sizeof ( buf ) );

	/* Draw row */
	attron ( A_BOLD );
	msg ( INFO_ROW, "%s - %s", buf, ui->row.setting.description );
	attroff ( A_BOLD );
	color_set ( CPAIR_URL, NULL );
	msg ( ( INFO_ROW + 1 ), PRODUCT_SETTING_URI, ui->row.setting.name );
	color_set ( CPAIR_NORMAL, NULL );
}

/**
 * Draw instruction row
 *
 * @v ui		Settings UI
 */
static void draw_instruction_row ( struct settings_ui *ui ) {

	clearmsg ( INSTRUCTION_ROW );
	if ( ui->row.editing ) {
		msg ( INSTRUCTION_ROW,
		      "Enter - accept changes" INSTRUCTION_PAD
		      "Ctrl-C - discard changes" );
	} else {
		msg ( INSTRUCTION_ROW,
		      "%sCtrl-X - exit configuration utility",
		      ( ( ui->row.origin == ui->settings ) ?
			"Ctrl-D - delete setting" INSTRUCTION_PAD : "" ) );
	}
}

/**
 * Draw the current block of setting rows
 *
 * @v ui		Settings UI
 */
static void draw_setting_rows ( struct settings_ui *ui ) {
	unsigned int i;

	/* Draw ellipses before and/or after the list as necessary */
	color_set ( CPAIR_SEPARATOR, NULL );
	mvaddstr ( ( SETTINGS_LIST_ROW - 1 ), ( SETTINGS_LIST_COL + 1 ),
		   jump_scroll_is_first ( &ui->scroll ) ? "   " : "..." );
	mvaddstr ( ( SETTINGS_LIST_ROW + SETTINGS_LIST_ROWS ),
		   ( SETTINGS_LIST_COL + 1 ),
		   jump_scroll_is_last ( &ui->scroll ) ? "   " : "..." );
	color_set ( CPAIR_NORMAL, NULL );

	/* Draw visible settings. */
	for ( i = 0 ; i < SETTINGS_LIST_ROWS ; i++ ) {
		if ( ( ui->scroll.first + i ) < ui->scroll.count ) {
			select_setting_row ( ui, ( ui->scroll.first + i ) );
			draw_setting_row ( ui );
		} else {
			clearmsg ( SETTINGS_LIST_ROW + i );
		}
	}
}

/**
 * Select settings block
 *
 * @v ui		Settings UI
 * @v settings		Settings block
 */
static void select_settings ( struct settings_ui *ui,
			      struct settings *settings ) {

	ui->settings = settings_target ( settings );
	ui->scroll.count = select_setting_row ( ui, 0 );
	ui->scroll.rows = SETTINGS_LIST_ROWS;
	ui->scroll.current = 0;
	ui->scroll.first = 0;
	draw_title_row ( ui );
	draw_setting_rows ( ui );
	select_setting_row ( ui, 0 );
}

static int main_loop ( struct settings *settings ) {
	struct settings_ui ui;
	unsigned int previous;
	int redraw = 1;
	int move;
	int key;
	int rc;

	/* Print initial screen content */
	color_set ( CPAIR_NORMAL, NULL );
	memset ( &ui, 0, sizeof ( ui ) );
	init_widgets ( &ui.widgets );
	select_settings ( &ui, settings );

	while ( 1 ) {

		/* Redraw rows if necessary */
		if ( redraw ) {
			draw_info_row ( &ui );
			draw_instruction_row ( &ui );
			color_set ( ( ui.row.editing ?
				      CPAIR_EDIT : CPAIR_SELECT ), NULL );
			draw_setting_row ( &ui );
			color_set ( CPAIR_NORMAL, NULL );
			curs_set ( ui.row.editing );
			redraw = 0;
		}

		/* Edit setting, if we are currently editing */
		if ( ui.row.editing ) {

			/* Sanity check */
			assert ( ui.row.setting.name != NULL );

			/* Redraw edit box */
			draw_widget ( &ui.row.editbox.widget );

			/* Process keypress */
			key = edit_setting ( &ui, getkey ( 0 ) );
			switch ( key ) {
			case CR:
			case LF:
				if ( ( rc = save_setting ( &ui ) ) != 0 )
					alert ( " %s ", strerror ( rc ) );
				/* Fall through */
			case CTRL_C:
				select_setting_row ( &ui, ui.scroll.current );
				redraw = 1;
				break;
			default:
				/* Do nothing */
				break;
			}

			continue;
		}

		/* Otherwise, navigate through settings */
		key = getkey ( 0 );
		move = jump_scroll_key ( &ui.scroll, key );
		if ( move ) {
			previous = ui.scroll.current;
			jump_scroll_move ( &ui.scroll, move );
			if ( ui.scroll.current != previous ) {
				draw_setting_row ( &ui );
				redraw = 1;
				if ( jump_scroll ( &ui.scroll ) )
					draw_setting_rows ( &ui );
				select_setting_row ( &ui, ui.scroll.current );
			}
			continue;
		}

		/* Handle non-navigation keys */
		switch ( key ) {
		case CTRL_D:
			if ( ! ui.row.setting.name )
				break;
			if ( ( rc = delete_setting ( ui.settings,
						     &ui.row.setting ) ) != 0 ){
				alert ( " %s ", strerror ( rc ) );
			}
			select_setting_row ( &ui, ui.scroll.current );
			redraw = 1;
			break;
		case CTRL_X:
			select_setting_row ( &ui, -1U );
			return 0;
		case CR:
		case LF:
			if ( ui.row.settings ) {
				select_settings ( &ui, ui.row.settings );
				redraw = 1;
			}
			/* Fall through */
		default:
			if ( ui.row.setting.name ) {
				edit_setting ( &ui, key );
				redraw = 1;
			}
			break;
		}
	}
}

int settings_ui ( struct settings *settings ) {
	int rc;

	initscr();
	start_color();
	color_set ( CPAIR_NORMAL, NULL );
	curs_set ( 0 );
	erase();
	
	rc = main_loop ( settings );

	endwin();

	return rc;
}
