/*
 * 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/>.
 *
 */


#ifndef GUI_H
#define GUI_H


#include "os.h"
#include "vesa.h"
#include "surface.h"
#include "array.h"
#include "mouse.h"
#include "font.h"
#include "rect.h"


#define GUI_GET_FLAG(w,f)   (((w)->flags & (1 << (f))) != 0)
#define GUI_SET_FLAG(w,f)   ((w)->flags |= (1 << (f)))
#define GUI_CLEAR_FLAG(w,f) ((w)->flags &= (~(1 << (f))))

#define W(w)  ((WidgetT *)w)
#define D(w)  ((WidgetT **)&w)


// Widget Magics.  Don't forget to change _magicDebugNames!
enum MagicE {
	MAGIC_UNKNOWN = 0,
	MAGIC_DESKTOP,
	MAGIC_WINDOW,
	MAGIC_BUTTON,
	MAGIC_LABEL,
	MAGIC_CHECKBOX,
	MAGIC_RADIOBUTTON,
	MAGIC_PICTURE,
	MAGIC_FRAME,
	MAGIC_TEXTBOX,
	MAGIC_UPDOWN,
	MAGIC_LISTBOX,
	MAGIC_TERMINAL,
	MAGIC_TIMER,
	//MAGIC_DROPDOWN,
	MAGIC_COUNT
};

// Widget Metrics
enum MetricE {
	METRIC_BUTTON_BEZEL_SIZE = 0,
	METRIC_BUTTON_HORIZONTAL_PADDING,
	METRIC_BUTTON_VERTICAL_PADDING,

	METRIC_WINDOW_BORDER_WIDTH,
	METRIC_WINDOW_TITLE_HEIGHT,
	METRIC_WINDOW_TITLE_GRAB_HEIGHT,

	METRIC_CHECKBOX_PADDING,

	METRIC_RADIOBUTTON_PADDING,

	METRIC_TEXTBOX_HORIZONTAL_PADDING,
	METRIC_TEXTBOX_VERTICAL_PADDING,
	METRIC_TEXTBOX_PADDING,

	METRIC_UPDOWN_PADDING,
	METRIC_UPDOWN_ARROW_PADDING,
	METRIC_UPDOWN_HORIZONTAL_PADDING,
	METRIC_UPDOWN_VERTICAL_PADDING,

	METRIC_LISTBOX_HORIZONTAL_PADDING,
	METRIC_LISTBOX_VERTICAL_PADDING,

	METRIC_COUNT
};

// Widget Colors
enum ColorE {
	COLOR_BUTTON_BACKGROUND = 0,
	COLOR_BUTTON_HIGHLIGHT,
	COLOR_BUTTON_SHADOW,
	COLOR_BUTTON_TEXT,
	COLOR_BUTTON_BACKGROUND_DISABLED,
	COLOR_BUTTON_HIGHLIGHT_DISABLED,
	COLOR_BUTTON_SHADOW_DISABLED,
	COLOR_BUTTON_TEXT_DISABLED,

	COLOR_DESKTOP,

	COLOR_WINDOW_BACKGROUND,
	COLOR_WINDOW_HIGHLIGHT,
	COLOR_WINDOW_SHADOW,
	COLOR_WINDOW_TITLE_ACTIVE,
	COLOR_WINDOW_TITLE_INACTIVE,
	COLOR_WINDOW_TITLE_TEXT_ACTIVE,
	COLOR_WINDOW_TITLE_TEXT_INACTIVE,

	COLOR_LABEL_TEXT_ACTIVE,
	COLOR_LABEL_TEXT_INACTIVE,

	COLOR_CHECKBOX_HIGHLIGHT,
	COLOR_CHECKBOX_SHADOW,
	COLOR_CHECKBOX_ACTIVE,
	COLOR_CHECKBOX_INACTIVE,
	COLOR_CHECKBOX_TEXT,
	COLOR_CHECKBOX_HIGHLIGHT_DISABLED,
	COLOR_CHECKBOX_SHADOW_DISABLED,
	COLOR_CHECKBOX_ACTIVE_DISABLED,
	COLOR_CHECKBOX_INACTIVE_DISABLED,
	COLOR_CHECKBOX_TEXT_DISABLED,

	COLOR_RADIOBUTTON_HIGHLIGHT,
	COLOR_RADIOBUTTON_SHADOW,
	COLOR_RADIOBUTTON_ACTIVE,
	COLOR_RADIOBUTTON_INACTIVE,
	COLOR_RADIOBUTTON_TEXT,
	COLOR_RADIOBUTTON_HIGHLIGHT_DISABLED,
	COLOR_RADIOBUTTON_SHADOW_DISABLED,
	COLOR_RADIOBUTTON_ACTIVE_DISABLED,
	COLOR_RADIOBUTTON_INACTIVE_DISABLED,
	COLOR_RADIOBUTTON_TEXT_DISABLED,

	COLOR_FRAME_HIGHLIGHT,
	COLOR_FRAME_SHADOW,
	COLOR_FRAME_TEXT,

	COLOR_TEXTBOX_HIGHLIGHT,
	COLOR_TEXTBOX_SHADOW,
	COLOR_TEXTBOX_TEXT,
	COLOR_TEXTBOX_BACKGROUND,

	COLOR_UPDOWN_HIGHLIGHT,
	COLOR_UPDOWN_SHADOW,
	COLOR_UPDOWN_TEXT,
	COLOR_UPDOWN_BACKGROUND,
	COLOR_UPDOWN_ARROWS_BACKGROUND,
	COLOR_UPDOWN_ARROWS_ACTIVE,
	COLOR_UPDOWN_ARROWS_INACTIVE,

	COLOR_LISTBOX_HIGHLIGHT,
	COLOR_LISTBOX_SHADOW,
	COLOR_LISTBOX_TEXT,
	COLOR_LISTBOX_BACKGROUND,
	COLOR_LISTBOX_SELECTED_TEXT,
	COLOR_LISTBOX_SELECTED_BACKGROUND,
	COLOR_LISTBOX_ARROWS_BACKGROUND,
	COLOR_LISTBOX_ARROWS_ACTIVE,
	COLOR_LISTBOX_ARROWS_INACTIVE,

	COLOR_COUNT
};

// Mouse Events
enum MouseE {
	MOUSE_EVENT_NONE = 0,
	MOUSE_EVENT_IN,
	MOUSE_EVENT_OUT,
	MOUSE_EVENT_LEFT_DOWN,
	MOUSE_EVENT_LEFT_HOLD,
	MOUSE_EVENT_LEFT_UP
};


typedef struct DesktopS DesktopT;
typedef struct WidgetS  WidgetT;
typedef struct WindowS  WindowT;


extern int16_t   _guiMetric[METRIC_COUNT];
extern ColorT    _guiColor[COLOR_COUNT];
extern FontT    *_guiFont;
extern WidgetT  *_guiDragWidget;
extern uint16_t  _guiDragOffsetX;
extern uint16_t  _guiDragOffsetY;
extern WindowT  *_guiActiveWindow;


void      guiAttach(WidgetT *parent, WidgetT *child);
void      guiComposite(void);
void      guiDebugAreaShow(WidgetT *widget);
void      guiDebugWidgetTreeDump(WidgetT *widget, uint16_t depth);
void      guiDelete(WidgetT **widget);
WidgetT  *guiFocusGet(void);
void      guiFocusSet(WidgetT *widget);
uint8_t   guiHasStopped(void);
void      guiKeyboardProcess(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
void      guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y);
void      guiMouseProcess(MouseT *mouse);
void      guiPaint(WidgetT *widget);
void      guiParentAndChildrenDirtySet(WidgetT *widget);
void      guiPendingEventAdd(WidgetT *widget, void *callback);
WidgetT  *guiRootGet(void);
void      guiShutdown(void);
DesktopT *guiStartup(void);
void      guiStop(void);
uint32_t  guiTimerGet(void);
uint8_t   guiTimerHalfSecondOn(void);
uint8_t   guiTimerHalfSecondTick(void);
void      guiTimerProcess(uint32_t rawClock);
uint8_t   guiTimerQuarterSecondOn(void);
uint8_t   guiTimerQuarterSecondTick(void);
uint8_t   guiTimerSecondOn(void);
uint8_t   guiTimerSecondTick(void);
void     *guiUserDataGet(WidgetT *widget);
void      guiUserDataSet(WidgetT *widget, void *userData);
void      guiWidgetAndChildrenDirtySet(WidgetT *widget);
void      guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds);
void      guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos);
WindowT  *guiWindowFindTop(void);


#endif // GUI_H
