#ifndef BREEZE_UI_CORE_H
#define BREEZE_UI_CORE_H

#include "../defines.h"

#include <raylib.h>

typedef u32 BzUIFlags;
typedef u32 BzUIKey;

typedef enum BzUISizeKind {
    BZ_UI_SIZE_NULL,
    BZ_UI_SIZE_PIXELS,
    BZ_UI_SIZE_FIT,
    BZ_UI_SIZE_REL_PARENT,
    BZ_UI_SIZE_AS_PARENT,
    BZ_UI_SIZE_CHILD_SUM,
    BZ_UI_SIZE_CHILD_MAX,
} BzUISizeKind;

typedef struct BzUISize {
    BzUISizeKind kind;
    f32 value;
} BzUISize;

typedef enum BzUILayoutType {
    BZ_UI_LAYOUT_NONE,
    BZ_UI_LAYOUT_UNIDIR,
    BZ_UI_LAYOUT_FLEX_BOX
} BzUILayoutType;

enum {
    // UNIDIRECTIONAL
    BZ_UI_UNIDIR_NONE   = 0,
    BZ_UI_UNIDIR_ROW    = (1 << 0),
    BZ_UI_UNIDIR_COLUMN = (1 << 1),
    BZ_UI_UNIDIR_WRAP   = (1 << 2),
    // FLEX BOX
    BZ_UI_FLEX_NONE                  = 0,
    BZ_UI_FLEX_DIR_ROW               = (1 << 0),
    BZ_UI_FLEX_DIR_COLUMN            = (1 << 1),
    BZ_UI_FLEX_ALIGN_START           = (1 << 2),
    BZ_UI_FLEX_ALIGN_CENTER          = (1 << 3),
    BZ_UI_FLEX_ALIGN_END             = (1 << 4),
    BZ_UI_FLEX_JUSTIFY_START         = (1 << 5),
    BZ_UI_FLEX_JUSTIFY_CENTER        = (1 << 6),
    BZ_UI_FLEX_JUSTIFY_END           = (1 << 7),
    BZ_UI_FLEX_JUSTIFY_SPACE_BETWEEN = (1 << 8),
    BZ_UI_FLEX_JUSTIFY_SPACE_AROUND  = (1 << 9),
    BZ_UI_FLEX_JUSTIFY_SPACE_EVENLY  = (1 << 10),
};

typedef struct BzUILayout {
    BzUILayoutType type;
    BzUIFlags      flags;
} BzUILayout;

typedef enum BzUIAxis {
    BZ_UI_AXIS_X,
    BZ_UI_AXIS_Y,
    BZ_UI_AXIS_COUNT,
} BzUIAxis;


typedef struct BzUIStyle {
    Font  font;
    f32   fontSize;
    f32   fontSpacing;
    f32   borderThickness;
    f32   roundness;
    f32   shadowOffset[BZ_UI_AXIS_COUNT];
    Color textColor;
    Color textHoverColor;
    Color textActiveColor;
    Color textShadowColor;
    Color textShadowHoverColor;
    Color textShadowActiveColor;
    Color bgColor;
    Color bgHoverColor;
    Color bgActiveColor;
    Color borderColor;
    Color borderHoverColor;
    Color borderActiveColor;
} BzUIStyle;


enum {
    BZ_UI_NONE               = 0,
    BZ_UI_CLICKABLE          = (1 << 0),
    BZ_UI_DRAW_DEBUG         = (1 << 1),
    BZ_UI_DRAW_BACKGROUND    = (1 << 2),
    BZ_UI_DRAW_BOX_SHADOW    = (1 << 3),
    BZ_UI_DRAW_BORDER        = (1 << 4),
    BZ_UI_DRAW_TEXT          = (1 << 5),
    BZ_UI_DRAW_TEXT_SHADOW   = (1 << 6),
    BZ_UI_DRAW_SPRITE        = (1 << 7),
    BZ_UI_ALIGN_HORIZ_START  = (1 << 8),
    BZ_UI_ALIGN_HORIZ_CENTER = (1 << 9),
    BZ_UI_ALIGN_HORIZ_END    = (1 << 10),
    BZ_UI_ALIGN_VERT_START   = (1 << 11),
    BZ_UI_ALIGN_VERT_CENTER  = (1 << 12),
    BZ_UI_ALIGN_VERT_END     = (1 << 13),

    BZ_UI_ALIGN_CENTER = BZ_UI_ALIGN_HORIZ_CENTER | BZ_UI_ALIGN_VERT_CENTER,
};

typedef struct BzUIBackgroundStyle {
    f32   thickness;
    f32   roundness;
    Color normal;
    Color hover;
    Color active;
} BzUIBackgroundStyle;

typedef struct BzUIBoxShadowStyle {
    f32                 offset[BZ_UI_AXIS_COUNT];
    BzUIBackgroundStyle bg;
} BzUIBoxShadowStyle;

typedef struct BzUIBorderStyle {
    f32   thickness;
    f32   roundness;
    Color normal;
    Color hover;
    Color active;
} BzUIBorderStyle;

typedef struct BzUITextStyle {
    const char *text;
    Font  font;
    f32   fontSize;
    f32   fontSpacing;
    Color normal;
    Color hover;
    Color active;
} BzUITextStyle;

typedef struct BzUITextShadowStyle {
    // Depends on BzUITextStyle
    f32   offset[BZ_UI_AXIS_COUNT];
    Color normal;
    Color hover;
    Color active;
} BzUITextShadowStyle;

typedef struct BzUISpriteStyle {
    Texture2D texture;
    Rectangle rec;

    Color tintNormal;
    Color tintHover;
    Color tintActive;
} BzUISpriteStyle;

typedef struct BzUINode BzUINode;

typedef struct BzUINodeDesc {
    BzUILayout  layout;
    BzUIFlags   flags;

    BzUISize semanticSize[BZ_UI_AXIS_COUNT];
    f32      padding[BZ_UI_AXIS_COUNT * 2];
    f32      margin[BZ_UI_AXIS_COUNT * 2];
} BzUINodeDesc;

typedef struct BzUIInteraction {
    bool pressed  : 1;
    bool down     : 1;
    bool released : 1;
    bool clicked  : 1;
    //bool dragging : 1;
    bool hovering : 1;
} BzUIInteraction;

typedef struct BzUI BzUI;

BzUIKey bzUIKeyNull();
BzUIKey bzUIKeyFromString(const char *str);

BzUI *bzUICreate();
void  bzUIDestroy(BzUI *ui);

bool bzUICapturedMouse(BzUI *ui);
bool bzUICapturedKeyboard(BzUI *ui);

bool bzUIGetCaptureMouse(BzUI *ui);
bool bzUIGetCaptureKeyboard(BzUI *ui);

void bzUISetCaptureMouse(BzUI *ui, bool state);
void bzUISetCaptureKeyboard(BzUI *ui, bool state);

void bzUIBegin(BzUI *ui, i32 width, i32 height);
void bzUIEnd(BzUI *ui);

BzUIKey bzUIGetUniqueKey(BzUI *ui);

BzUINode *bzUINodeMake(BzUI *ui, BzUIKey key, const BzUINodeDesc *desc);

BzUINode *bzUIPushDiv(BzUI *ui, BzUISize x, BzUISize y);
BzUINode *bzUIPushParent(BzUI *ui, BzUINode *node);
BzUINode *bzUIPopParent(BzUI *ui);

// Styles

BzUIBackgroundStyle bzUIGetBackgroundStyle(const BzUI *ui, BzUINode *node);
BzUIBoxShadowStyle  bzUIGetBoxShadowStyle(const BzUI *ui, BzUINode *node);
BzUITextStyle       bzUIGetTextStyle(const BzUI *ui, BzUINode *node);
BzUITextShadowStyle bzUIGetTextShadowStyle(const BzUI *ui, BzUINode *node);
BzUIBorderStyle     bzUIGetBorderStyle(const BzUI *ui, BzUINode *node);
BzUISpriteStyle     bzUIGetSpriteStyle(const BzUI *ui, BzUINode *node);

void bzUISetBackgroundStyle(BzUI *ui, BzUINode *node, BzUIBackgroundStyle style);
void bzUISetBoxShadowStyle(BzUI *ui, BzUINode *node, BzUIBoxShadowStyle style);
void bzUISetTextStyle(BzUI *ui, BzUINode *node, BzUITextStyle style);
void bzUISetTextShadowStyle(BzUI *ui, BzUINode *node, BzUITextShadowStyle style);
void bzUISetBorderStyle(BzUI *ui, BzUINode *node, BzUIBorderStyle style);
void bzUISetSpriteStyle(BzUI *ui, BzUINode *node, BzUISpriteStyle style);

BzUILayout bzUIGetLayout(const BzUI *ui, BzUINode *node);
void       bzUISetLayout(BzUI *ui, BzUINode *node, BzUILayout layout);

void bzUISetParentLayout(BzUI *ui, BzUILayout layout);

BzUIInteraction bzUIGetInteraction(BzUI *ui, BzUINode *node);

bool bzUIButton(BzUI *ui, const char *string);

#endif //BREEZE_UI_CORE_H
