/*
 * DWN - Desktop Window Manager
 * retoor <retoor@molodetz.nl>
 * Main header with shared types and global state
 */

#ifndef DWN_H
#define DWN_H

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xft/Xft.h>
#include <stdbool.h>
#include <stdint.h>

#define DWN_VERSION "1.0.0"
#define DWN_NAME "DWN"

#define MAX_CLIENTS 256
#define MAX_WORKSPACES 9
#define MAX_MONITORS 8
#define MAX_NOTIFICATIONS 32
#define MAX_KEYBINDINGS 64

#define RESIZE_LEFT   1
#define RESIZE_RIGHT  2
#define RESIZE_TOP    4
#define RESIZE_BOTTOM 8

#define DEFAULT_BORDER_WIDTH 0
#define DEFAULT_TITLE_HEIGHT 28
#define DEFAULT_PANEL_HEIGHT 32
#define DEFAULT_GAP 0

typedef enum {
    DWN_OK = 0,
    DWN_ERROR = -1,
    DWN_ERROR_INVALID_ARG = -2,
    DWN_ERROR_NO_MEMORY = -3,
    DWN_ERROR_NOT_FOUND = -4,
    DWN_ERROR_DISPLAY = -5,
    DWN_ERROR_IO = -6
} DwnStatus;

typedef enum {
    LAYOUT_TILING,
    LAYOUT_FLOATING,
    LAYOUT_MONOCLE,
    LAYOUT_CENTERED_MASTER,
    LAYOUT_COLUMNS,
    LAYOUT_FIBONACCI,
    LAYOUT_COUNT
} LayoutType;

typedef enum {
    FOCUS_CLICK,
    FOCUS_FOLLOW
} FocusMode;

typedef enum {
    CLIENT_NORMAL     = 0,
    CLIENT_FLOATING   = (1 << 0),
    CLIENT_FULLSCREEN = (1 << 1),
    CLIENT_URGENT     = (1 << 2),
    CLIENT_MINIMIZED  = (1 << 3),
    CLIENT_STICKY     = (1 << 4),
    CLIENT_MAXIMIZED  = (1 << 5),
    CLIENT_UNMANAGING = (1 << 6)  /* Being destroyed, skip processing */
} ClientFlags;

typedef enum {
    SNAP_H_NONE = 0,
    SNAP_H_LEFT,
    SNAP_H_RIGHT,
    SNAP_H_FULL
} SnapHorizontal;

typedef enum {
    SNAP_V_NONE = 0,
    SNAP_V_TOP,
    SNAP_V_BOTTOM,
    SNAP_V_FULL
} SnapVertical;

typedef struct {
    SnapHorizontal horizontal;
    SnapVertical vertical;
    long timestamp;
} SnapConstraint;

typedef struct {
    long start_time;
    float progress;
    unsigned long from_color;
    unsigned long to_color;
    bool active;
} ColorAnimation;

typedef struct {
    float phase;
    float speed;
    unsigned long base_color;
    bool active;
} TextGlowAnimation;

typedef struct Client Client;
typedef struct Workspace Workspace;
typedef struct Monitor Monitor;
typedef struct Panel Panel;
typedef struct Config Config;

struct Client {
    Window window;
    Window frame;
    int x, y;
    int width, height;
    int old_x, old_y;
    int old_width, old_height;
    int border_width;
    uint32_t flags;
    unsigned int workspace;
    char title[256];
    char class[64];
    SnapConstraint snap;
    unsigned long taskbar_color;
    ColorAnimation title_anim;
    TextGlowAnimation text_glow;
    Client *next;
    Client *prev;
    Client *mru_next;
    Client *mru_prev;
};

struct Monitor {
    int x, y;
    int width, height;
    int index;
    bool primary;
};

struct Workspace {
    Client *clients;
    Client *focused;
    Client *mru_head;
    Client *mru_tail;
    LayoutType layout;
    float master_ratio;
    int master_count;
    char name[32];
};

typedef enum {
    WIDGET_WORKSPACES,
    WIDGET_TASKBAR,
    WIDGET_CLOCK,
    WIDGET_SYSTRAY,
    WIDGET_AI_STATUS,
    WIDGET_SEPARATOR
} WidgetType;

typedef struct {
    Display *display;
    int screen;
    Window root;
    int screen_width;
    int screen_height;

    Monitor monitors[MAX_MONITORS];
    int monitor_count;

    Workspace workspaces[MAX_WORKSPACES];
    int current_workspace;

    Client *client_list;
    int client_count;

    Panel *top_panel;
    Panel *bottom_panel;

    Config *config;

    bool running;
    bool ai_enabled;

    GC gc;
    XFontStruct *font;
    XftFont *xft_font;
    XftFont *xft_font_bold;
    Colormap colormap;

    Client *drag_client;
    int drag_start_x, drag_start_y;
    int drag_orig_x, drag_orig_y;
    int drag_orig_w, drag_orig_h;
    bool resizing;
    int drag_direction;

    Client *pending_focus_client;
    long pending_focus_time;

    bool is_alt_tabbing;
    Client *alt_tab_client;

    bool desktop_shown;
    Window desktop_minimized[MAX_CLIENTS];
    int desktop_minimized_count;

    float ambient_phase;
    float ambient_speed;
    long typing_activity_time;

    unsigned long key_press_count;
    long key_delete_flicker_time;
    int xi2_opcode;
    double mouse_distance_pixels;
    int last_mouse_x;
    int last_mouse_y;
    bool mouse_tracking_initialized;
} DWNState;

#define PHASE_OFFSET_PANEL_BG      0.0f
#define PHASE_OFFSET_WORKSPACES    0.8f
#define PHASE_OFFSET_TASKBAR       1.6f
#define PHASE_OFFSET_CLOCK         2.4f
#define PHASE_OFFSET_STATS         3.2f
#define PHASE_OFFSET_TOP_MEM       4.0f
#define PHASE_OFFSET_TOP_CPU       4.4f
#define PHASE_OFFSET_DECORATIONS   4.8f
#define PHASE_OFFSET_SYSTRAY       5.6f
#define PHASE_OFFSET_NEWS          1.2f
#define PHASE_OFFSET_KEY_COUNTER   5.2f
#define PHASE_OFFSET_MOUSE_DIST    5.8f
#define PHASE_OFFSET_DISK_SPACE    6.2f

extern DWNState *dwn;

int dwn_init(void);
void dwn_cleanup(void);
void dwn_run(void);
void dwn_quit(void);

void dwn_handle_event(XEvent *ev);

#endif
