/*
 * DWN - Desktop Window Manager
 * Abstract Workspace Interface
 */

#ifndef WM_WORKSPACE_H
#define WM_WORKSPACE_H

#include "wm_types.h"
#include "wm_client.h"

#ifdef __cplusplus
extern "C" {
#endif

/*==============================================================================
 * Workspace Configuration
 *============================================================================*/

#define WM_MAX_WORKSPACES 32

typedef struct {
    WmLayoutType layout_type;
    float master_ratio;
    int master_count;
    char name[64];
    bool persistent;
    WmString *custom_data;
} WmWorkspaceConfig;

/*==============================================================================
 * Workspace Lifecycle
 *============================================================================*/

bool wm_workspace_exists(WmCore *core, WmWorkspaceId id);
WmWorkspaceId wm_workspace_create(WmCore *core, const char *name);
void wm_workspace_destroy(WmCore *core, WmWorkspaceId id);

void wm_workspace_init_all(WmCore *core);
void wm_workspace_cleanup_all(WmCore *core);

/*==============================================================================
 * Workspace Properties
 *============================================================================*/

const char* wm_workspace_get_name(WmCore *core, WmWorkspaceId id);
void wm_workspace_set_name(WmCore *core, WmWorkspaceId id, const char *name);

bool wm_workspace_is_empty(WmCore *core, WmWorkspaceId id);
size_t wm_workspace_get_client_count(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Current Workspace
 *============================================================================*/

WmWorkspaceId wm_workspace_get_current(WmCore *core);
void wm_workspace_set_current(WmCore *core, WmWorkspaceId id);
void wm_workspace_switch(WmCore *core, WmWorkspaceId id);

void wm_workspace_switch_next(WmCore *core);
void wm_workspace_switch_prev(WmCore *core);

/*==============================================================================
 * Client Management
 *============================================================================*/

void wm_workspace_add_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);
void wm_workspace_remove_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);
void wm_workspace_move_client(WmCore *core, AbstractClient *client, WmWorkspaceId to_workspace);

WmContainer* wm_workspace_get_clients(WmCore *core, WmWorkspaceId id);

AbstractClient* wm_workspace_get_focused_client(WmCore *core, WmWorkspaceId id);
void wm_workspace_set_focused_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);

AbstractClient* wm_workspace_get_first_client(WmCore *core, WmWorkspaceId id);
AbstractClient* wm_workspace_get_last_client(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Layout Management
 *============================================================================*/

WmLayoutType wm_workspace_get_layout(WmCore *core, WmWorkspaceId id);
void wm_workspace_set_layout(WmCore *core, WmWorkspaceId id, WmLayoutType layout);
void wm_workspace_cycle_layout(WmCore *core, WmWorkspaceId id);
void wm_workspace_cycle_layout_reverse(WmCore *core, WmWorkspaceId id);

float wm_workspace_get_master_ratio(WmCore *core, WmWorkspaceId id);
void wm_workspace_set_master_ratio(WmCore *core, WmWorkspaceId id, float ratio);
void wm_workspace_adjust_master_ratio(WmCore *core, WmWorkspaceId id, float delta);

int wm_workspace_get_master_count(WmCore *core, WmWorkspaceId id);
void wm_workspace_set_master_count(WmCore *core, WmWorkspaceId id, int count);
void wm_workspace_adjust_master_count(WmCore *core, WmWorkspaceId id, int delta);

/*==============================================================================
 * Workspace Arrangement
 *============================================================================*/

void wm_workspace_arrange(WmCore *core, WmWorkspaceId id);
void wm_workspace_arrange_all(WmCore *core);
void wm_workspace_arrange_current(WmCore *core);

WmRect wm_workspace_get_arrange_area(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Workspace Visibility
 *============================================================================*/

void wm_workspace_show(WmCore *core, WmWorkspaceId id);
void wm_workspace_hide(WmCore *core, WmWorkspaceId id);
bool wm_workspace_is_visible(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Focus Management
 *============================================================================*/

void wm_workspace_focus_next(WmCore *core, WmWorkspaceId id);
void wm_workspace_focus_prev(WmCore *core, WmWorkspaceId id);
void wm_workspace_focus_master(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * MRU (Most Recently Used) Stack
 *============================================================================*/

void wm_workspace_mru_push(WmCore *core, WmWorkspaceId id, AbstractClient *client);
void wm_workspace_mru_remove(WmCore *core, WmWorkspaceId id, AbstractClient *client);
AbstractClient* wm_workspace_mru_get_next(WmCore *core, WmWorkspaceId id, AbstractClient *current);
AbstractClient* wm_workspace_mru_get_prev(WmCore *core, WmWorkspaceId id, AbstractClient *current);

/*==============================================================================
 * Alt-Tab Navigation
 *============================================================================*/

void wm_workspace_alt_tab_start(WmCore *core, WmWorkspaceId id);
void wm_workspace_alt_tab_next(WmCore *core, WmWorkspaceId id);
void wm_workspace_alt_tab_prev(WmCore *core, WmWorkspaceId id);
void wm_workspace_alt_tab_end(WmCore *core, WmWorkspaceId id);
bool wm_workspace_alt_tab_is_active(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Workspace Iteration
 *============================================================================*/

WmWorkspaceId wm_workspace_get_first(WmCore *core);
WmWorkspaceId wm_workspace_get_last(WmCore *core);
WmWorkspaceId wm_workspace_get_next(WmCore *core, WmWorkspaceId id);
WmWorkspaceId wm_workspace_get_prev(WmCore *core, WmWorkspaceId id);

/*==============================================================================
 * Configuration
 *============================================================================*/

void wm_workspace_save_config(WmCore *core, WmWorkspaceId id, const WmWorkspaceConfig *config);
bool wm_workspace_load_config(WmCore *core, WmWorkspaceId id, WmWorkspaceConfig *config);

#ifdef __cplusplus
}
#endif

#endif /* WM_WORKSPACE_H */
