/*
 * DWN - Desktop Window Manager
 * Monocle Layout Plugin (Built-in)
 */

#include "plugins/layout_plugin.h"
#include "core/wm_client.h"
#include "util.h"

#include <stdlib.h>

/*==============================================================================
 * Monocle Layout State
 *============================================================================*/

typedef struct {
    int focused_index;  /* Which client is currently visible */
} MonocleState;

/*==============================================================================
 * Monocle Layout Interface
 *============================================================================*/

static bool monocle_init(LayoutPlugin *plugin) {
    LOG_INFO("Monocle layout initialized");
    (void)plugin;
    return true;
}

static void monocle_shutdown(LayoutPlugin *plugin) {
    LOG_INFO("Monocle layout shutdown");
    (void)plugin;
}

static WmLayoutState* monocle_state_create(LayoutPlugin *plugin, WmWorkspaceId workspace) {
    (void)plugin;
    (void)workspace;
    
    MonocleState *ms = calloc(1, sizeof(MonocleState));
    ms->focused_index = 0;
    return (WmLayoutState*)ms;
}

static void monocle_state_destroy(LayoutPlugin *plugin, WmLayoutState *state) {
    (void)plugin;
    free(state);
}

static void monocle_state_reset(LayoutPlugin *plugin, WmLayoutState *state) {
    (void)plugin;
    if (state) {
        MonocleState *ms = (MonocleState*)state;
        ms->focused_index = 0;
    }
}

/*==============================================================================
 * Monocle Layout Calculation
 *============================================================================*/

static bool monocle_arrange(LayoutPlugin *plugin, LayoutContext *ctx,
                             AbstractClient **clients, int num_clients,
                             WmLayoutGeometry *geometries) {
    (void)plugin;
    (void)clients;
    
    if (num_clients == 0) return true;
    
    WmLayoutWorkArea *wa = &ctx->work_area;
    int gap = ctx->gap;
    
    /* Calculate effective work area with padding */
    int wx = wa->x + wa->padding_left + gap;
    int wy = wa->y + wa->padding_top + gap;
    int ww = wa->width - wa->padding_left - wa->padding_right - gap * 2;
    int wh = wa->height - wa->padding_top - wa->padding_bottom - gap * 2;
    
    /* All clients take full area - they will be stacked */
    for (int i = 0; i < num_clients; i++) {
        geometries[i].x = wx;
        geometries[i].y = wy;
        geometries[i].width = ww;
        geometries[i].height = wh;
        geometries[i].floating = false;
        geometries[i].hidden = false;
        geometries[i].fullscreen = false;
    }
    
    return true;
}

/*==============================================================================
 * Layout Manipulation
 *============================================================================*/

static void monocle_rotate(LayoutPlugin *plugin, LayoutContext *ctx, bool clockwise) {
    (void)plugin;
    (void)ctx;
    
    if (!ctx->state) return;
    
    MonocleState *ms = (MonocleState*)ctx->state;
    
    if (clockwise) {
        ms->focused_index++;
        if (ms->focused_index >= ctx->client_count) {
            ms->focused_index = 0;
        }
    } else {
        ms->focused_index--;
        if (ms->focused_index < 0) {
            ms->focused_index = ctx->client_count - 1;
        }
    }
}

/*==============================================================================
 * Layout Configuration Parameters
 *============================================================================*/

static WmLayoutParameter monocle_parameters[] = {
    {
        .name = "gaps",
        .description = "Show gaps around the monocle window",
        .type = WM_LAYOUT_PARAM_BOOL,
        .default_value.bool_value = false
    },
    {
        .name = "bar_height",
        .description = "Height of client indicator bar",
        .type = WM_LAYOUT_PARAM_INT,
        .default_value.int_value = 4
    }
};

/*==============================================================================
 * Layout Plugin Interface
 *============================================================================*/

static LayoutPluginInterface monocle_interface = {
    .api_version = WM_LAYOUT_PLUGIN_API_VERSION,
    .name = "monocle",
    .description = "Monocle layout - one maximized window at a time",
    .author = "DWN",
    .version = "1.0",
    
    .parameters = monocle_parameters,
    .num_parameters = sizeof(monocle_parameters) / sizeof(monocle_parameters[0]),
    
    .init = monocle_init,
    .shutdown = monocle_shutdown,
    
    .state_create = monocle_state_create,
    .state_destroy = monocle_state_destroy,
    .state_reset = monocle_state_reset,
    
    .config_parse = NULL,
    .config_apply = NULL,
    
    .arrange = monocle_arrange,
    
    .client_added = NULL,
    .client_removed = NULL,
    .client_floating_changed = NULL,
    
    .inc_master = NULL,
    .set_master_ratio = NULL,
    .set_master_count = NULL,
    .swap_master = NULL,
    .rotate = monocle_rotate,
    .resize_master = NULL
};

/*==============================================================================
 * Exported Interface
 *============================================================================*/

const LayoutPluginInterface* wm_layout_monocle_get_interface(void) {
    return &monocle_interface;
}

WM_LAYOUT_REGISTER(monocle, monocle_interface)
