#include <graphics/layer.h>
#include <graphics/draw.h>
#include <graphics/context.h>
#include <memory/heap.h>
#include <memory/pmm.h>
#include <scheduler.h>
#include <serial.h>
#include <interrupt/idt.h>
#include <interrupt/pic.h>
#include <string_utils.h>

// 图层列表（按 z 排序，最低在前）

static layer_t g_layers[LAYER_MAX];
static UINT32  g_layer_count = 0;
static layer_t* g_layer_list = NULL;

// 合成器后台缓冲区
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL* g_back_buffer = NULL;

// 焦点追踪
static layer_t* g_focused = NULL;

// Shift+F10 状态（由 IRQ 处理函数设置，合成器消费）
static volatile bool     g_shift_held = false;
static volatile bool     g_switch_pending = false;
static volatile layer_t* g_switch_target = NULL;

// PS/2 扫描码集 1
#define PS2_F10        0x44
#define PS2_LSHIFT     0x2A
#define PS2_RSHIFT     0x36
#define PS2_BREAK_BIT  0x80

// 前向声明
static void layer_insert_sorted(layer_t* layer);
static void layer_remove(layer_t* layer);
static layer_t* find_next_window(layer_t* from);

// PS/2 键盘 IRQ 处理
static void ps2_irq_handler(trap_frame* frame) {
    (void)frame;
    pic_send_eoi(1);

    UINT8 sc;
    ASM("inb %1, %0" : "=a"(sc) : "Nd"((UINT16)0x60));

    bool is_break = (sc & PS2_BREAK_BIT) != 0;
    UINT8 code = sc & 0x7F;

    if (code == PS2_LSHIFT || code == PS2_RSHIFT) {
        g_shift_held = !is_break;
        return;
    }

    if (!is_break && g_shift_held && code == PS2_F10) {
        layer_t* next = find_next_window((layer_t*)g_focused);
        if (next) {
            g_switch_target = next;
            g_switch_pending = true;
        }
    }
}

// 图层管理
layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h) {
    if (g_layer_count >= LAYER_MAX) {
        serial_write("LAYER: limit reached\n");
        return NULL;
    }

    UINT32 id = g_layer_count++;
    layer_t* layer = &g_layers[id];

    layer->id = id;
    layer->type = type;
    layer->x = 0;
    layer->y = 0;
    layer->w = w;
    layer->h = h;
    layer->z = 0;
    layer->visible = true;
    layer->next = NULL;

    str_copy(layer->name, name, LAYER_NAME_LEN);

    UINTN buf_size = (UINTN)w * h * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    layer->buffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)kmalloc(buf_size);
    if (!layer->buffer) {
        serial_write("LAYER: buffer alloc failed for ");
        serial_write(name);
        serial_write("\n");
        g_layer_count--;
        return NULL;
    }

    EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = layer->buffer;
    for (UINTN i = 0; i < (UINTN)w * h; i++) {
        p->Blue = 0; p->Green = 0; p->Red = 0; p->Reserved = 0;
        p++;
    }

    layer_insert_sorted(layer);

    serial_write("LAYER: created '");
    serial_write(name);
    serial_write("' id=");
    serial_write_hex(id);
    serial_write("\n");

    return layer;
}

void layer_destroy(layer_t* layer) {
    if (!layer) return;

    layer_remove(layer);

    if (layer->buffer) {
        kfree(layer->buffer);
        layer->buffer = NULL;
    }

    if (g_focused == layer) g_focused = NULL;
    if (g_switch_target == layer) {
        g_switch_target = NULL;
        g_switch_pending = false;
    }

    serial_write("LAYER: destroyed '");
    serial_write(layer->name);
    serial_write("'\n");
}

layer_t* layer_get_by_id(UINT32 id) {
    if (id >= LAYER_MAX) return NULL;
    layer_t* l = &g_layers[id];
    return l->buffer ? l : NULL;
}

layer_t* layer_get_focused(void) {
    return g_focused;
}

void layer_set_z(layer_t* layer, SSINT32 z) {
    if (!layer) return;
    layer_remove(layer);
    layer->z = z;
    layer_insert_sorted(layer);
}

void layer_set_pos(layer_t* layer, SSINT32 x, SSINT32 y) {
    if (!layer) return;
    layer->x = x;
    layer->y = y;
}

void layer_set_visible(layer_t* layer, bool visible) {
    if (!layer) return;
    layer->visible = visible;
}

// 有序插入/移除
static void layer_insert_sorted(layer_t* layer) {
    layer->next = NULL;

    if (!g_layer_list || layer->z < g_layer_list->z) {
        layer->next = g_layer_list;
        g_layer_list = layer;
        return;
    }

    layer_t* cur = g_layer_list;
    while (cur->next && cur->next->z <= layer->z) {
        cur = cur->next;
    }
    layer->next = cur->next;
    cur->next = layer;
}

static void layer_remove(layer_t* layer) {
    if (!g_layer_list) return;

    if (g_layer_list == layer) {
        g_layer_list = layer->next;
        layer->next = NULL;
        return;
    }

    layer_t* cur = g_layer_list;
    while (cur->next && cur->next != layer) {
        cur = cur->next;
    }
    if (cur->next == layer) {
        cur->next = layer->next;
        layer->next = NULL;
    }
}

static layer_t* find_next_window(layer_t* from) {
    layer_t* start = from ? from->next : g_layer_list;
    if (!start) start = g_layer_list;

    layer_t* cur = start;
    do {
        if (cur->type == LAYER_TYPE_WINDOW && cur->visible) {
            return cur;
        }
        cur = cur->next;
        if (!cur) cur = g_layer_list;
    } while (cur != start);

    return NULL;
}

// 初始化
void layer_init(void) {
    UINT32 hr = g_gfx.hr;
    UINT32 vr = g_gfx.vr;

    UINTN buf_size = (UINTN)hr * vr * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
    g_back_buffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)kmalloc(buf_size);
    if (!g_back_buffer) {
        serial_write("LAYER: back buffer alloc FAILED\n");
        return;
    }

    EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = g_back_buffer;
    for (UINTN i = 0; i < (UINTN)hr * vr; i++) {
        p->Blue = 0; p->Green = 0; p->Red = 0; p->Reserved = 0;
        p++;
    }

    // 注册键盘 IRQ 并取消屏蔽
    idt_set_handler(PIC_IRQ_BASE + 1, ps2_irq_handler);
    pic_unmask_irq(1);

    serial_write("LAYER: compositor init OK (back buffer = ");
    serial_write_hex(buf_size);
    serial_write(" bytes)\n");
}

// 合成器任务
void layer_compositor_task(void) {
    serial_write("LAYER: compositor task running\n");

    UINT32 hr = g_gfx.hr;
    UINT32 vr = g_gfx.vr;

    while (1) {
        // 处理延迟的 Shift+F10 窗口切换
        if (g_switch_pending) {
            g_switch_pending = false;
            layer_t* target = (layer_t*)g_switch_target;
            if (target && target->visible && target->type == LAYER_TYPE_WINDOW) {
                g_focused = target;
                layer_set_z(target, 99);
                serial_write("LAYER: Shift+F10 -> '");
                serial_write(target->name);
                serial_write("'\n");
            }
        }

        // 清除后台缓冲区
        EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
        draw_set_target(g_back_buffer, hr, vr);
        draw_rect(0, 0, hr, vr, black);
        draw_set_default_target();

        // 按 z 从低到高合成图层
        layer_t* cur = g_layer_list;
        while (cur) {
            if (cur->visible && cur->buffer) {
                SSINT32 sx = 0, sy = 0;
                SSINT32 dx = cur->x, dy = cur->y;
                UINT32 sw = cur->w, sh = cur->h;

                if (dx < 0) { sx = -dx; sw -= sx; dx = 0; }
                if (dy < 0) { sy = -dy; sh -= sy; dy = 0; }
                if (dx + (SSINT32)sw > (SSINT32)hr) sw = hr - dx;
                if (dy + (SSINT32)sh > (SSINT32)vr) sh = vr - dy;
                if (sw == 0 || sh == 0) { cur = cur->next; continue; }

                for (UINT32 row = 0; row < sh; row++) {
                    EFI_GRAPHICS_OUTPUT_BLT_PIXEL* src = cur->buffer + ((UINTN)cur->w * (sy + row)) + sx;
                    EFI_GRAPHICS_OUTPUT_BLT_PIXEL* dst = g_back_buffer + ((UINTN)hr * (dy + row)) + dx;
                    for (UINT32 col = 0; col < sw; col++) {
                        dst->Blue  = src->Blue;
                        dst->Green = src->Green;
                        dst->Red   = src->Red;
                        dst->Reserved = src->Reserved;
                        src++;
                        dst++;
                    }
                }
            }
            cur = cur->next;
        }

        // Blit 到屏幕
        uefi_call_wrapper(g_gfx.GOP->Blt, 10,
            g_gfx.GOP,
            g_back_buffer,
            EfiBltBufferToVideo,
            (UINTN)0, (UINTN)0, (UINTN)0, (UINTN)0,
            (UINTN)hr, (UINTN)vr, (UINTN)0
        );

        yield();
    }
}
