/*
 * 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 "checkbox.h"


static void checkboxDel(WidgetT **widget);
static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
static void checkboxPaint(WidgetT *widget, uint8_t enabled, RectT pos);


void checkboxClickHandlerSet(CheckboxT *checkbox, widgetCallback callback) {
	checkbox->clicked = callback;
}


static void checkboxDel(WidgetT **widget) {
	CheckboxT *c = (CheckboxT *)*widget;

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


WidgetT *checkboxInit(WidgetT *widget, char *title) {
	CheckboxT *c = (CheckboxT *)widget;

	c->base.delMethod        = checkboxDel;
	c->base.paintMethod      = checkboxPaint;
	c->base.mouseEventMethod = checkboxMouseEvent;
	c->title                 = NULL;
	c->clicked               = NULL;

	checkboxTitleSet(c, title);

	return widget;
}


static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
	CheckboxT *c = (CheckboxT *)widget;

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

	if (event == MOUSE_EVENT_LEFT_UP) {
		// Toggle value.
		checkboxValueSet(c, !checkboxValueGet(c));
		// Fire callback on mouse up.
		if (c->clicked) guiPendingEventAdd(widget, c->clicked);
	}
}


CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title) {
	CheckboxT *checkbox = (CheckboxT *)malloc(sizeof(CheckboxT));
	WidgetT   *widget   = NULL;
	uint16_t   h        = fontHeightGet(_guiFont);

	if (!checkbox) return NULL;

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

	checkbox = (CheckboxT *)checkboxInit((WidgetT *)checkbox,  title);

	return checkbox;
}


static void checkboxPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
	CheckboxT *c = (CheckboxT *)widget;
	int16_t    o;
	int8_t     active;
	ColorT     highlight;
	ColorT     shadow;
	ColorT     fill;
	ColorT     text;
	ColorT     background;

	active    = checkboxValueGet(c);
	if (enabled) {
		highlight  = active ? _guiColor[COLOR_CHECKBOX_SHADOW] : _guiColor[COLOR_CHECKBOX_HIGHLIGHT];
		shadow     = active ? _guiColor[COLOR_CHECKBOX_HIGHLIGHT] : _guiColor[COLOR_CHECKBOX_SHADOW];
		fill       = active ? _guiColor[COLOR_CHECKBOX_ACTIVE] : _guiColor[COLOR_CHECKBOX_INACTIVE];
		text       = _guiColor[COLOR_CHECKBOX_TEXT];
		background = _guiColor[COLOR_WINDOW_BACKGROUND];
	} else {
		highlight  = active ? _guiColor[COLOR_CHECKBOX_SHADOW_DISABLED] : _guiColor[COLOR_CHECKBOX_HIGHLIGHT_DISABLED];
		shadow     = active ? _guiColor[COLOR_CHECKBOX_HIGHLIGHT_DISABLED] : _guiColor[COLOR_CHECKBOX_SHADOW_DISABLED];
		fill       = active ? _guiColor[COLOR_CHECKBOX_ACTIVE_DISABLED] : _guiColor[COLOR_CHECKBOX_INACTIVE_DISABLED];
		text       = _guiColor[COLOR_CHECKBOX_TEXT_DISABLED];
		background = _guiColor[COLOR_WINDOW_BACKGROUND];
	}

	// Checkbox is 10x10 pixels.  Find offset based on font height.
	o = (_guiFont->height - 10) * 0.5;

	// Draw outline of checkbox.
	surfaceHighlightFrameDraw(pos.x, pos.y + o, pos.x + 10, pos.y + 10 + o, highlight, shadow);

	// Draw background.
	surfaceRectangleFilledDraw(pos.x + 1, pos.y + o + 1, pos.x + 9, pos.y + + o + 9, fill);

	// Draw title.
	fontRender(_guiFont, c->title, text, background, pos.x + 10 + _guiMetric[METRIC_CHECKBOX_PADDING], pos.y);
}


void checkboxTitleSet(CheckboxT *checkbox, char *title) {
	if (checkbox->title) free(checkbox->title);
	checkbox->title = strdup(title);
	checkbox->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)) + 10 + _guiMetric[METRIC_CHECKBOX_PADDING];
	GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_DIRTY);
}


uint8_t checkboxValueGet(CheckboxT *checkbox) {
	return GUI_GET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_ACTIVE);
}


void checkboxValueSet(CheckboxT *checkbox, uint8_t selected) {
	if (selected) {
		if (!checkboxValueGet(checkbox)) {
			GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_ACTIVE);
			GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_DIRTY);
		}
	} else {
		if (checkboxValueGet(checkbox)) {
			GUI_CLEAR_FLAG((WidgetT *)checkbox, WIDGET_FLAG_ACTIVE);
			GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_DIRTY);
		}
	}
}

