#include <libmbtk/callback.h>
#include <libmbtk/callback_imp.h>
#include "topwin.h"

static void rnd_mbtk_topwin_alloc(rnd_mbtk_t *mctx)
{
	mctx->topwin = calloc(sizeof(rnd_mbtk_topwin_t), 1);
}

static const unsigned long rnd_dock_color[RND_HID_DOCK_max] = {0, 0, 0xffaa33ffUL, 0, 0, 0}; /* force change color when docked */

static mbtk_event_handled_t topwin_event(mbtk_widget_t *w, mbtk_kw_t id, mbtk_event_t *ev, void *user_data)
{
	rnd_mbtk_t *mctx = user_data;
	switch(ev->type) {
		case MBTK_EV_KEY_PRESS: return rnd_mbtk_key_press_cb(mctx, ev);
		case MBTK_EV_KEY_RELEASE: return rnd_mbtk_key_release_cb(mctx, ev);
		case MBTK_EV_RSTDIN: return rnd_mbtk_stdin_input(mctx, ev);
		default:
			break;
	}
	return MBTK_EVENT_NOT_HANDLED;
}

static mbtk_event_handled_t tw_main_drawing_event(mbtk_widget_t *w, mbtk_kw_t id, mbtk_event_t *ev, void *user_data)
{
	rnd_mbtk_t *mctx = user_data;
	rnd_hid_cfg_mod_t mods;
	static int pressed_button;

	switch(ev->type) {
		case MBTK_EV_MOUSE_PRESS:
			if (pressed_button > 0)
				return MBTK_EVENT_NOT_HANDLED;

			rnd_trace("click %d\n", ev->data.mouse.button);
			if (mbtk_button_event(mctx, ev))
				return MBTK_EVENT_HANDLED;

			rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_false);
			pressed_button = ev->data.mouse.button;
			mods = mbtk_mod2cfg(mbtk_display_query_kbd_mods(&mctx->disp));
			rnd_hid_cfg_mouse_action(mctx->hidlib, &mctx->hc_mouse, mbtk_mb2cfg(ev->data.mouse.button) | mods, mctx->cmd_is_active);
			rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_true);
			return MBTK_EVENT_HANDLED;

		case MBTK_EV_MOUSE_RELEASE:
			if (ev->data.mouse.button != pressed_button)
				return MBTK_EVENT_NOT_HANDLED;

			rnd_trace("release %d\n", ev->data.mouse.button);
			mbtk_button_event(mctx, ev);

			rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_false);
			pressed_button = 0;
			mods = mbtk_mod2cfg(mbtk_display_query_kbd_mods(&mctx->disp)) + RND_M_Release;
			rnd_hid_cfg_mouse_action(mctx->hidlib, &mctx->hc_mouse, mbtk_mb2cfg(ev->data.mouse.button) | mods, mctx->cmd_is_active);
			rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_true);
			return MBTK_EVENT_HANDLED;

		case MBTK_EV_MOUSE_MOTION:
			mctx->in_move_event = 1;
			rnd_trace("moveto %d %d\n", ev->data.mouse.x, ev->data.mouse.y);
			mctx->crosshair_move_to(mctx, ev->data.mouse.x, ev->data.mouse.y);
			mctx->in_move_event = 0;
			return MBTK_EVENT_HANDLED;

		case MBTK_EV_MOUSE_SCROLL:
			if (ev->data.mouse.y != 0) {
				rnd_trace("scroll %d %d\n", ev->data.mouse.x, ev->data.mouse.y);
				rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_false);
				mods = mbtk_mod2cfg(mbtk_display_query_kbd_mods(&mctx->disp));
				mods |= ((ev->data.mouse.y > 0) ? RND_MB_SCROLL_UP : RND_MB_SCROLL_DOWN);
				rnd_hid_cfg_mouse_action(mctx->hidlib, &mctx->hc_mouse, mods, mctx->cmd_is_active);
				rnd_hid_notify_crosshair_change(mctx->hidlib, rnd_true);
				return MBTK_EVENT_HANDLED;
			}
			break;
	}

	return MBTK_EVENT_NOT_HANDLED;
}


static int tw_drawing_area_first_draw_cb(mbtk_canvas_native_t *c, void *native_ctx, long x_offs, long y_offs, long w, long h)
{
	rnd_mbtk_t *mctx = c->w.user_data;
	int res;

	res = mctx->main_drawing_area_first_draw_cb(c, native_ctx, x_offs, y_offs, w, h);

	/* redirect the callback of subequent draws to the normal draw callback proc */
	mbtk_canvas_native_set_draw_cb(c, mctx->main_drawing_area_draw_cb);
	return res;
}

static void rnd_mbtk_populate_topwin(rnd_mbtk_t *mctx)
{
	rnd_mbtk_topwin_t *tw = mctx->topwin;
	

	mbtk_vbox_new(&tw->vbox_main);
	mbtk_window_set_root_widget(tw->win, &tw->vbox_main.w);
	mbtk_handler_ev2cb_install(&tw->vbox_main.w);
	mbtk_callback_set_event(&tw->vbox_main.w, mbtk_kw("event"), topwin_event, mctx);

	/*** top control bar ***/
	mbtk_hbox_new(&tw->top_bar_background);
	mbtk_box_add_widget(&tw->vbox_main, &tw->top_bar_background.w, 0);

	mbtk_hbox_new(&tw->top_hbox);
	mbtk_box_set_span(&tw->top_hbox, HVBOX_FILL);
	mbtk_box_add_widget(&tw->top_bar_background, &tw->top_hbox.w, 0);

	/* menu_hbox will be disabled when the GUI waits for a get_coords */
	mbtk_hbox_new(&tw->menu_hbox);
	mbtk_box_add_widget(&tw->top_hbox, &tw->menu_hbox.w, 0);

	mbtk_vbox_new(&tw->menubar_toolbar_vbox);
	mbtk_box_add_widget(&tw->menu_hbox, &tw->menubar_toolbar_vbox.w, 0);

	/* top left: main menu and toolbar */
	mbtk_menu_bar_new(&tw->menu_bar);
	mbtk_box_add_widget(&tw->menubar_toolbar_vbox, &tw->menu_bar.w, 0);

	mbtk_hbox_new(&tw->dockbox[RND_HID_DOCK_TOP_LEFT]);
	mbtk_box_add_widget(&tw->menubar_toolbar_vbox, &tw->dockbox[RND_HID_DOCK_TOP_LEFT].w, 0);

	/* pushes the top right position box to the right */
	mbtk_hbox_new(&tw->top_spring);
	mbtk_box_set_span(&tw->top_spring, HVBOX_FILL);
	mbtk_box_add_widget(&tw->top_hbox, &tw->top_spring.w, 0);

	/* top right */
	mbtk_hbox_new(&tw->position_hbox);
	mbtk_box_add_widget(&tw->top_hbox, &tw->position_hbox.w, 0);

	mbtk_vbox_new(&tw->dockbox[RND_HID_DOCK_TOP_RIGHT]);
	mbtk_box_add_widget(&tw->position_hbox, &tw->dockbox[RND_HID_DOCK_TOP_RIGHT].w, 0);

	/*** middle section ***/
	mbtk_pane_new(&tw->hpaned_middle, 1);
	mbtk_pane_set_span(&tw->hpaned_middle, HVBOX_FILL);
	mbtk_pane_set_pixel(&tw->hpaned_middle, 150); /* convenient default */
	mbtk_box_add_widget(&tw->vbox_main, &tw->hpaned_middle.w, 0);

	/* the left toolbar box will be disabled in get_coords */
	mbtk_vbox_new(&tw->left_toolbar);
	mbtk_pane_set_child(&tw->hpaned_middle, 0, &tw->left_toolbar.w);

	mbtk_vbox_new(&tw->dockbox[RND_HID_DOCK_LEFT]);
	mbtk_box_set_span(&tw->dockbox[RND_HID_DOCK_LEFT], HVBOX_FILL);
	mbtk_box_add_widget(&tw->left_toolbar, &tw->dockbox[RND_HID_DOCK_LEFT].w, 0);

	/*** right side is our main content: drawing area with scroll bars ***/
	mbtk_vbox_new(&tw->vbox_middle);
	mbtk_box_set_span(&tw->vbox_middle, HVBOX_FILL);
	mbtk_pane_set_child(&tw->hpaned_middle, 1, &tw->vbox_middle.w);

	/* first the info box */
	mbtk_hbox_new(&tw->info_hbox);
	mbtk_box_add_widget(&tw->vbox_middle, &tw->info_hbox.w, 0);

	if (rnd_dock_color[RND_HID_DOCK_TOP_INFOBAR] != 0)
		mbtk_box_style_set_prop(&tw->info_hbox, mbtk_kw("bg.color"), mbtk_arg_long(rnd_dock_color[RND_HID_DOCK_TOP_INFOBAR]));

#ifdef TODO_REAL_CODE
	mbtk_hbox_new(&tw->dockbox[RND_HID_DOCK_TOP_INFOBAR]);
	mbtk_box_set_span(&tw->dockbox[RND_HID_DOCK_TOP_INFOBAR], HVBOX_FILL);
	mbtk_box_add_widget(&tw->info_hbox, &tw->dockbox[RND_HID_DOCK_TOP_INFOBAR], 0);
#else
	TODO("remove this");
	mbtk_box_add_widget(&tw->info_hbox, (mbtk_widget_t *)mbtk_label_new(NULL, "info-box!"),0);
#endif

	/* the drawing area is in a hbox with a vertical scrollbar */
	mbtk_hbox_new(&tw->drw_hbox1);
	mbtk_box_set_span(&tw->drw_hbox1, HVBOX_FILL);
	mbtk_box_add_widget(&tw->vbox_middle, &tw->drw_hbox1.w, 0);

	mbtk_canvas_native_new(&tw->drawing_area);
	mbtk_canvas_native_set_span(&tw->drawing_area, HVBOX_FILL);
	mbtk_canvas_native_set_draw_cb(&mctx->topwin->drawing_area, tw_drawing_area_first_draw_cb);
	mctx->topwin->drawing_area.w.user_data = mctx;
	mbtk_callback_set_event(&tw->drawing_area.w, mbtk_kw("event"), tw_main_drawing_event, mctx);
	mbtk_box_add_widget(&tw->drw_hbox1, &tw->drawing_area.w, 0);

	mbtk_scrollbar_new(&tw->vscroll, 0);
	mbtk_box_add_widget(&tw->drw_hbox1, &tw->vscroll.w, 0);

	/* horizontal scrollbar and fullscreen button in another hbox */
	mbtk_hbox_new(&tw->drw_hbox2);
	mbtk_box_add_widget(&tw->vbox_middle, &tw->drw_hbox2.w, 0);

	mbtk_scrollbar_new(&tw->hscroll, 1);
	mbtk_scrollbar_set_span(&tw->hscroll, HVBOX_FILL);
	mbtk_box_add_widget(&tw->drw_hbox2, &tw->hscroll.w, 0);

	TODO("switch over to static allocation, use full screen XPM");
	{
		mbtk_button_t *btn = mbtk_button_new_with_label("FS");
		mbtk_box_add_widget(&tw->drw_hbox2, &btn->w, 0);
	}

	/*** bottom status bar ***/
	mbtk_hbox_new(&tw->bottom_hbox);
	mbtk_box_add_widget(&tw->vbox_middle, &tw->bottom_hbox.w, 0);

	mbtk_hbox_new(&tw->dockbox[RND_HID_DOCK_BOTTOM]);
	mbtk_box_add_widget(&tw->bottom_hbox, &tw->dockbox[RND_HID_DOCK_BOTTOM].w, 0);

	mbtk_label_new(&tw->cmd_prompt, "action:");
	mbtk_box_add_widget(&tw->bottom_hbox, &tw->cmd_prompt.w, 0);

/*	rnd_gtk_command_combo_box_entry_create(&tw->cmd, rnd_gtk_topwin_hide_status, tw);*/
	mbtk_combo_new(&tw->cmd);
	mbtk_combo_set_span(&tw->cmd, HVBOX_FILL);
	mbtk_box_add_widget(&tw->bottom_hbox, &tw->cmd.w, 0);

	mbtk_widget_hide(&tw->cmd_prompt.w, 0);
	mbtk_widget_hide(&tw->cmd.w, 1);

	rnd_mbtk_load_menus(mctx);


	TODO("implement these:");
/*
	gtkc_bind_mouse_enter(tw->drawing_area, rnd_gtkc_xy_ev(&ghidgui->wtop_enter, drawing_area_enter_cb, tw));
	gtk2c_bind_win_resize(ghidgui->wtop_window, rnd_gtkc_xy_ev(&ghidgui->wtop_rs, top_window_configure_event_cb, tw));
	gtkc_bind_win_delete(ghidgui->wtop_window, rnd_gtkc_xy_ev(&ghidgui->wtop_del, delete_chart_cb, ctx));
	gtkc_bind_win_destroy(ghidgui->wtop_window, rnd_gtkc_xy_ev(&ghidgui->wtop_destr, destroy_chart_cb, ctx));

	gtk4c_bind_win_resize(ghidgui->wtop_window, rnd_gtkc_xy_ev(&ghidgui->wtop_rs, top_window_configure_event_cb, tw));

	rnd_gtk_fullscreen_apply(tw);
*/

	tw->active = 1;
}

static void rnd_mbtk_topwin_free(rnd_mbtk_t *mctx)
{
	free(mctx->topwin);
	mctx->topwin = NULL;
}
