/*
 *   MediaMVP Server Widget Library
 *
 *   (C) 2004 Dave Kelly
 *
 *   $Id: menu.c,v 1.2 2004/08/30 08:55:24 ravelox Exp $
 *   $Date: 2004/08/30 08:55:24 $
 *
 *   Window handling
 *
 */


#include "mvpwindow.h"

#define MENU_ROTATIONAL			1
#define MENU_ITEM_DISPLAY_CHANGED	2

#define BLACK   0x00000000
#define RED     0x00FC1414
#define GREEN   0x0024FC24
#define YELLOW  0x00FCC024
#define BLUE    0x000000FC
#define CYAN    0x0000FCFC
#define MAGENTA 0x00B000FC
#define WHITE   0x00FCFCFC

static void      menu_set_border_size(window_t *menu, int border_size);
static void      menu_set_border_col(window_t *menu, uint32_t border_col);
static void      menu_set_fill_col(window_t *menu, uint32_t fill_col);
static void      menu_set_font(window_t *menu, font_t *font);

static uint32_t  menu_get_fill_col(window_t *window);
static uint32_t  menu_get_border_col(window_t *window);
static int       menu_get_border_size(window_t *window);
static font_t   *menu_get_font(window_t *window);

static void      draw_menu(window_t *menu);
static void      delete_menu_data(window_t *menu);
static int       calc_display_items(window_t *menu);
static int       menu_handle_event(window_t *window, int keycode, void *appdata);

static attrib_fns_t menu_fns = {
	0,
	menu_set_fill_col,
	menu_set_border_col,
	menu_set_border_size,
	menu_set_font,
	NULL,
	NULL,
	menu_get_fill_col,
	menu_get_border_col,
	menu_get_border_size,
	menu_get_font,
	NULL,
	NULL
};

typedef struct {
	int flags;
	window_t *title_label;
	int num_items;
	window_t **labels;
	int sel;
	uint32_t sel_fgcol, sel_bgcol;
	uint32_t unsel_fgcol, unsel_bgcol;
	font_t *item_font;
	int max_display_items;
	int top_item, bottom_item;
	window_t *box;
    window_t   *colours[4];   
} menu_t;



window_t *new_menu(window_t *parent, int x, int y, int width, int height)
{
	window_t *window;
	menu_t *menu;


	window = new_window(parent, WINDOW_MENU, x, y, width, height);
	window_set_attrib_fns(window, &menu_fns);

	menu = (menu_t *)malloc(sizeof(menu_t));

	menu->flags = MENU_ROTATIONAL | MENU_ITEM_DISPLAY_CHANGED;
	menu->num_items = 0;
	menu->labels = NULL;
	menu->title_label = NULL;
	menu->sel_fgcol = WHITE;
	menu->sel_bgcol = GREEN;
	menu->unsel_fgcol = WHITE;
	menu->unsel_bgcol = BLACK;
	menu->max_display_items = 0;
	menu->top_item = 0;
	menu->bottom_item = 0;
	menu->sel = 0;
	menu->item_font = font_read(default_font);

	window_set_name(window, "%internal% menu");
	window_set_data(window, menu);

	window_set_draw_func(window, draw_menu);
	window_set_delete_func(window, delete_menu_data);
	window_set_event_func(window, menu_handle_event);

	menu->title_label = new_label(window, 0,0, width, font_get_height(menu->item_font), "%internal% menu title");
	window_set_name(menu->title_label, "%internal% menu title");
	label_set_align(menu->title_label, LABEL_ALIGN_CENTRE);
	window_set_bgcol(menu->title_label, WHITE);
	window_set_fgcol(menu->title_label, BLACK);

	menu->box = new_box(window,0,font_get_height(menu->item_font), width, height - font_get_height(menu->item_font));
	window_set_name(menu->box, "%internal% menu box");
	window_set_border_size(menu->box, 5);
	window_set_border_col(menu->box, GREEN);

	window_mark_dirty(window);

	return window;
}

void menu_add_item(window_t *menu, char *text)
{
	menu_t *data = NULL;
	int width = 0;
	int border_size = 0;
    int i;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! text) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}


	data->labels = (window_t **)realloc(data->labels, (data->num_items + 1) * sizeof(window_t *));
	width = window_get_width(data->box);
	border_size = window_get_border_size(data->box);
	data->labels[data->num_items] = new_label(data->box, 0, 0, width - (2 * border_size) , font_get_height(data->item_font), text);
	window_set_visible(data->labels[data->num_items], 0);
	window_set_name(data->labels[data->num_items], text);
	window_set_font(data->labels[data->num_items], data->item_font);
	window_mark_dirty(data->labels[data->num_items]);

	window_set_fgcol(data->labels[data->num_items], data->unsel_fgcol);
	window_set_bgcol(data->labels[data->num_items], data->unsel_bgcol);
	data->num_items++;

	data->max_display_items = calc_display_items(menu);

	if(data->max_display_items > data->num_items) {
		data->max_display_items = data->num_items;
	}

	if(data->bottom_item < data->max_display_items) {
		data->bottom_item  = (data->num_items < data->max_display_items ? 
				data->num_items - 1 : data->max_display_items - 1);
	}

	menu_set_sel(menu, data->sel,FALSE);

	window_mark_dirty(data->box);
	window_mark_dirty(menu);
}

static void menu_set_border_size(window_t *menu, int border_size)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	window_set_border_size(data->box, border_size);
}

static void menu_set_border_col(window_t *menu, uint32_t border_col)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	window_set_border_col(data->box , border_col);
}

static void menu_set_fill_col(window_t *menu, uint32_t fill_col)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	window_set_fill_col(data->box, fill_col);
}

static void menu_set_font(window_t *menu, font_t *font)
{
	menu_t *data;
	int i=0;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! font) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->item_font = font;

	for(i=0 ; i < data->num_items; i++) {
		window_set_font(data->labels[i], data->item_font);
	}

	window_mark_dirty(menu);
}

static uint32_t menu_get_border_col(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	return window_get_border_col(data->box);
}

static uint32_t menu_get_fill_col(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	return window_get_fill_col(data->box);
}

static int menu_get_border_size(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	return window_get_border_size(data->box);
}

static font_t *menu_get_font(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return NULL;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return NULL;
	}

	return data->item_font;
}

void menu_set_item_sel_fgcol(window_t *menu, uint32_t fgcol)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->sel_fgcol = fgcol;
	window_mark_dirty(menu);
}

void menu_set_item_sel_bgcol(window_t *menu, uint32_t bgcol)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->sel_bgcol = bgcol;
	window_mark_dirty(menu);
}

void menu_set_item_unsel_fgcol(window_t *menu, uint32_t fgcol)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->unsel_fgcol = fgcol;
	window_mark_dirty(menu);
}

void menu_set_item_unsel_bgcol(window_t *menu, uint32_t bgcol)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->unsel_bgcol = bgcol;
	window_mark_dirty(menu);
}

int menu_get_num_items(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	return data->num_items;
}

int menu_get_sel(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	return data->sel;
}

static int calc_display_items(window_t *menu)
{
	menu_t *data;
	int menu_height, font_height;

	if(window_get_type(menu) != WINDOW_MENU) {
		return 0;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return 0;
	}

	menu_height = window_get_height(data->box) - (2 * window_get_border_size(data->box));
	font_height = font_get_height(data->item_font);

    /* If we've got colour actions then decrease the size by one line */
    if ( data->colours[0] || data->colours[1] || data->colours[2] || data->colours[3] ) {
        menu_height -= font_height;
    }

	return (menu_height / font_height);
}

static void delete_menu_data(window_t *menu)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	data->labels = NULL;
	data->item_font = NULL;

    data->colours[0] = data->colours[1] = data->colours[2] = data->colours[3] = NULL;

    free(data);

	return;
}

void menu_set_sel(window_t *menu, int sel, bool_t wrap)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

    if ( data->num_items == 0 ) {
        return;
    }

	if(sel < 0 || sel >= data->num_items) {
		if(! (data->flags & MENU_ROTATIONAL) ) {
			return;
		}
		
		if(sel < 0 ) {
            if ( wrap == TRUE) {
                sel = data->num_items - 1;
            } else {
                sel = 0;
            }
		}

		if(sel >= data->num_items) {
            if ( wrap == TRUE ) {
                sel = 0;
            } else {
                sel = data->num_items - 1;
            }
		}
	}

	if(sel < data->top_item) {
		data->top_item = sel;
		data->bottom_item = sel + data->max_display_items - 1;
		data->flags |= MENU_ITEM_DISPLAY_CHANGED;
	} else if(sel > data->bottom_item) {
		data->bottom_item = sel;
		data->top_item = sel - (data->max_display_items - 1);
		data->flags |= MENU_ITEM_DISPLAY_CHANGED;
	}

	/* Limit the range */
	if(data->top_item < 0) {
		data->top_item = 0;
	}
	if(data->bottom_item >= data->num_items) {
		data->bottom_item = data->num_items - 1;
	}

	window_set_bgcol(data->labels[data->sel],data->unsel_bgcol);
	window_set_fgcol(data->labels[data->sel],data->unsel_fgcol);

	window_set_bgcol(data->labels[sel],data->sel_bgcol);
	window_set_fgcol(data->labels[sel],data->sel_fgcol);

	data->sel = sel;

	window_mark_dirty(menu);
}

static void draw_menu(window_t *menu)
{
	menu_t *data;
	int i,j;
	int border_size = 0;
	int font_height = 0;

	if( window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	if(! (data->flags & MENU_ITEM_DISPLAY_CHANGED)) {
		return;
	}

	/* Unset all the labels being displayed */
	for( i = 0 ; i < data->num_items ; i++) {
		window_set_visible(data->labels[i], 0);
	}

	font_height = font_get_height(data->item_font);
	border_size = window_get_border_size(data->box);

	j = 0;
	for(i = data->top_item ; i <= data->bottom_item && data->num_items != 0  ; i++) {
		window_set_visible(data->labels[i], 1);
		window_set_pos(data->labels[i], border_size, border_size + ( (j++) * font_height ) );
	}

    for ( i = 0; i < 4; i++ ) {


    }

	data->flags &= ~MENU_ITEM_DISPLAY_CHANGED;
	window_mark_dirty(data->box);
}

static int menu_handle_event(window_t *window, int keycode, void *appdata)
{
	menu_t  *data;
	int return_state = 0;
	int sel;

	if(window_get_type(window) == WINDOW_MENU) {

        if(! (data = (menu_t *)window_get_data(window)) ) {
            return return_state;
        }

		sel = menu_get_sel(window);
		switch(keycode) {
        case keyOk:
            if ( menu_get_num_items(window) > 0 ) {
                window_raise_event(window, event_select, &sel);
            }
            return_state = EVENT_HANDLED;
            break;
        case keyChanUp:
            if ( menu_get_num_items(window) > 0 ) {
                menu_set_sel(window, sel - 1,TRUE);
                window_raise_event(window, event_highlight, NULL);
            }
            return_state = EVENT_HANDLED;
            break;
        case keyChanDn:
            if ( menu_get_num_items(window) > 0 ) {
                menu_set_sel(window, sel + 1,TRUE);
                window_raise_event(window, event_highlight, NULL);
            }
            return_state = EVENT_HANDLED;
            break;
        case keyVolUp:
            if ( menu_get_num_items(window) > 0 ) {
                menu_set_sel(window, sel + data->max_display_items - 1,FALSE);
                window_raise_event(window, event_highlight, NULL);
            }
            return_state = EVENT_HANDLED;
            break;
        case keyVolDn:
            if ( menu_get_num_items(window) > 0 ) {
                menu_set_sel(window, sel - ( data->max_display_items - 1),FALSE);
                window_raise_event(window, event_highlight, NULL);
            }
            return_state = EVENT_HANDLED;
            break;
		}
	}

	return return_state;
}

void menu_set_title(window_t *menu, char *title)
{
	menu_t *data;

	if(window_get_type(menu) != WINDOW_MENU) {
		return;
	}

	if(! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

	label_set_text(data->title_label, title);
	window_mark_dirty(menu);
}



void menu_set_colour_text(window_t *menu, char *red, char *green, char *yellow, char *blue)
{
    int      font_height;
    menu_t  *data;
    int      y;

	if ( window_get_type(menu) != WINDOW_MENU ) {
		return;
	}

	if( ! (data = (menu_t *)window_get_data(menu)) ) {
		return;
	}

    font_height = font_get_height(data->item_font);

    y = window_get_height(data->box) - font_height;

    if ( red ) {
        data->colours[0] = new_label(data->box,0,y, window_get_width(menu) / 4 , font_height, red);
        window_set_bgcol(data->colours[0], RED);
        window_set_fgcol(data->colours[0], BLACK);
        label_set_align(data->colours[0], LABEL_ALIGN_CENTRE);
        label_set_valign(data->colours[0], LABEL_VALIGN_MIDDLE);
    }

    if ( green ) {
        data->colours[1] = new_label(data->box,window_get_width(menu) / 4,y , window_get_width(menu) / 4, font_height, green);
        window_set_bgcol(data->colours[1], GREEN);
        window_set_fgcol(data->colours[1], BLACK);
        label_set_align(data->colours[1], LABEL_ALIGN_CENTRE);
        label_set_valign(data->colours[1], LABEL_VALIGN_MIDDLE);
    }
    if ( yellow ) {
        data->colours[2] = new_label(data->box,window_get_width(menu) / 2, y, window_get_width(menu) / 4, font_height, yellow);
        window_set_bgcol(data->colours[2], YELLOW);
        window_set_fgcol(data->colours[2], BLACK);
        label_set_align(data->colours[2], LABEL_ALIGN_CENTRE);
        label_set_valign(data->colours[2], LABEL_VALIGN_MIDDLE);
    }
    if ( blue ) {
        data->colours[3] = new_label(data->box,(window_get_width(menu) / 4) * 3, y, window_get_width(menu) / 4, font_height, blue);
        window_set_bgcol(data->colours[3], BLUE);
        window_set_fgcol(data->colours[3], WHITE);
        label_set_align(data->colours[3], LABEL_ALIGN_CENTRE);
        label_set_valign(data->colours[3], LABEL_VALIGN_MIDDLE);
    }

    /* Fix up height display */
	data->max_display_items = calc_display_items(menu);

	if(data->max_display_items > data->num_items) {
		data->max_display_items = data->num_items;
	}

	if(data->bottom_item < data->max_display_items) {
		data->bottom_item  = (data->num_items < data->max_display_items ? 
				data->num_items - 1 : data->max_display_items - 1);
	}


}
