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

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

#include <stdlib.h>
#include <math.h>

/*==============================================================================
 * Grid Layout Interface
 *============================================================================*/

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

static void grid_shutdown(LayoutPlugin *plugin) {
    LOG_INFO("Grid layout shutdown");
    (void)plugin;
}

static WmLayoutState* grid_state_create(LayoutPlugin *plugin, WmWorkspaceId workspace) {
    (void)plugin;
    (void)workspace;
    return NULL;
}

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

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

/*==============================================================================
 * Grid Layout Calculation
 *============================================================================*/

static bool grid_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;
    
    if (num_clients == 1) {
        geometries[0].x = wx;
        geometries[0].y = wy;
        geometries[0].width = ww;
        geometries[0].height = wh;
        geometries[0].floating = false;
        return true;
    }
    
    /* Calculate grid dimensions */
    int cols = (int)ceil(sqrt(num_clients));
    int rows = (num_clients + cols - 1) / cols;
    
    /* Adjust for gap */
    int cell_w = (ww - gap * (cols - 1)) / cols;
    int cell_h = (wh - gap * (rows - 1)) / rows;
    int extra_w = (ww - gap * (cols - 1)) % cols;
    int extra_h = (wh - gap * (rows - 1)) % rows;
    
    for (int i = 0; i < num_clients; i++) {
        int col = i % cols;
        int row = i / cols;
        
        geometries[i].x = wx + col * (cell_w + gap);
        geometries[i].y = wy + row * (cell_h + gap);
        geometries[i].width = cell_w + (col < extra_w ? 1 : 0);
        geometries[i].height = cell_h + (row < extra_h ? 1 : 0);
        geometries[i].floating = false;
        
        /* Last row might have fewer cells */
        if (row == rows - 1) {
            int remaining = num_clients - row * cols;
            if (cols > remaining) {
                /* Center the remaining cells */
                int offset = (ww - (remaining * cell_w + (remaining - 1) * gap)) / 2;
                geometries[i].x = wx + offset + col * (cell_w + gap);
            }
        }
    }
    
    return true;
}

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

static WmLayoutParameter grid_parameters[] = {
    {
        .name = "gap",
        .description = "Gap between windows in pixels",
        .type = WM_LAYOUT_PARAM_INT,
        .default_value.int_value = 0
    }
};

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

static LayoutPluginInterface grid_interface = {
    .api_version = WM_LAYOUT_PLUGIN_API_VERSION,
    .name = "grid",
    .description = "Grid layout - windows arranged in a grid pattern",
    .author = "DWN",
    .version = "1.0",
    
    .parameters = grid_parameters,
    .num_parameters = sizeof(grid_parameters) / sizeof(grid_parameters[0]),
    
    .init = grid_init,
    .shutdown = grid_shutdown,
    
    .state_create = grid_state_create,
    .state_destroy = grid_state_destroy,
    .state_reset = grid_state_reset,
    
    .config_parse = NULL,
    .config_apply = NULL,
    
    .arrange = grid_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 = NULL,
    .resize_master = NULL
};

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

const LayoutPluginInterface* wm_layout_grid_get_interface(void) {
    return &grid_interface;
}

WM_LAYOUT_REGISTER(grid, grid_interface)
