/*
 * Kangaroo Punch MultiPlayer Game Server Mark II
 * Copyright (C) 2020-2021  Scott Duensing
 *
 * 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 3 of the License, or
 * (at your option) 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, see <https://www.gnu.org/licenses/>.
 *
 */


#include "button.h"


static void buttonDel(WidgetT **widget);
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
static void buttonPaint(WidgetT *widget, uint8_t enabled, RectT pos);


void buttonClickHandlerSet(ButtonT *button, widgetCallback callback) {
	button->clicked = callback;
}


static void buttonDel(WidgetT **widget) {
	ButtonT *b = (ButtonT *)*widget;

	if (b->title) free(b->title);
}


WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback) {
	ButtonT *b = (ButtonT *)button;

	b->base.delMethod        = buttonDel;
	b->base.paintMethod      = buttonPaint;
	b->base.mouseEventMethod = buttonMouseEvent;
	b->title                 = NULL;

	buttonClickHandlerSet(b, callback);

	// Width is set in buttonSetTitle
	buttonTitleSet(b, title);

	return button;
}


static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
	ButtonT *b = (ButtonT *)widget;

	(void)x;
	(void)y;
	(void)mouse;

	// Button pressed?
	if (event == MOUSE_EVENT_LEFT_HOLD) {
		if (!GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) {
			GUI_SET_FLAG(widget, WIDGET_FLAG_ACTIVE);
			GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
		}
	} else {
		if (GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) {
			GUI_CLEAR_FLAG(widget, WIDGET_FLAG_ACTIVE);
			GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
		}
	}

	// Fire callback on mouse up.
	if (event == MOUSE_EVENT_LEFT_UP) {
		if (b->clicked) guiPendingEventAdd(widget, b->clicked);
	}
}


ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback) {
	ButtonT  *button = (ButtonT *)malloc(sizeof(ButtonT));
	WidgetT  *widget = NULL;
	uint16_t  h      = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);


	if (!button) return NULL;

	// Width is set in Init.
	widget = widgetInit(W(button), MAGIC_BUTTON, x, y, 0, h, 0, 0, 0, 0);
	if (!widget) {
		free(button);
		return NULL;
	}

	button = (ButtonT *)buttonInit((WidgetT *)button, title, callback);

	return button;
}


static void buttonPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
	ButtonT  *b;
	int16_t   i;
	int8_t    active;
	ColorT    highlight;
	ColorT    shadow;
	ColorT    background;
	ColorT    text;

	b = (ButtonT *)widget;
	active    = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE);

	if (enabled) {
		highlight  = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT];
		shadow     = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW];
		background = _guiColor[COLOR_BUTTON_BACKGROUND];
		text       = _guiColor[COLOR_BUTTON_TEXT];
	} else {
		highlight  = active ? _guiColor[COLOR_BUTTON_SHADOW_DISABLED] : _guiColor[COLOR_BUTTON_HIGHLIGHT_DISABLED];
		shadow     = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT_DISABLED] : _guiColor[COLOR_BUTTON_SHADOW_DISABLED];
		background = _guiColor[COLOR_BUTTON_BACKGROUND_DISABLED];
		text       = _guiColor[COLOR_BUTTON_TEXT_DISABLED];
	}

	// Draw bezel.
	for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) {
		surfaceHighlightFrameDraw(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.h - i, highlight, shadow);
	}

	// Draw background (depends on x from above).
	surfaceRectangleFilledDraw(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.h - i, background);

	// Draw title (depends on x from above).
	fontRender(_guiFont, b->title, text, background, pos.x + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] + active, pos.y + i + _guiMetric[METRIC_BUTTON_VERTICAL_PADDING] + active);
}


void buttonTitleSet(ButtonT *button, char *title) {
	if (button->title) free(button->title);
	button->title = strdup(title);
	button->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
	GUI_SET_FLAG((WidgetT *)button, WIDGET_FLAG_DIRTY);
}
