// Copyright (c) 2023-2026 Chris (boreddevnl)
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
// This header needs to maintain in any file it is present in, as per the GPL license terms.
#include "wm.h"
#include "graphics.h"
#include "io.h"
#include "cmd.h"
#include "process.h"
#include "syscall.h"
#include "kutils.h"
#include "explorer.h"
#include <stdbool.h>
#include <stddef.h>
#include "wallpaper.h"
#include "fat32.h"
#include "nanojpeg.h"
#include "memory_manager.h"
#include "disk.h"

extern void serial_write(const char *str);

static bool str_eq(const char *s1, const char *s2) {
    if (!s1 || !s2) return false;
    while (*s1 && *s2) {
        if (*s1 != *s2) return false;
        s1++; s2++;
    }
    return (*s1 == *s2);
}

// --- State ---
static int mx = 400, my = 300; 
static int prev_mx = 400, prev_my = 300; 
static bool start_menu_open = false;
static char *start_menu_pending_app = NULL; 
static int pending_desktop_icon_click = -1; 

// Desktop Context Menu
static bool desktop_menu_visible = false;
static int desktop_menu_x = 0;
static int desktop_menu_y = 0;
static int desktop_menu_target_icon = -1; 

// Desktop Dialog State
static int desktop_dialog_state = 0; 
static char desktop_dialog_input[64];
static int desktop_dialog_cursor = 0;
static int desktop_dialog_target = -1;

// Message Box
static bool msg_box_visible = false;
static char msg_box_title[64];
static char msg_box_text[64];

// Hook definition
void (*wm_custom_paint_hook)(void) = NULL;

// Dragging State
static bool is_dragging = false;
static Window *drag_window = NULL;
static int drag_offset_x = 0;
static int drag_offset_y = 0;

// File Dragging State
bool is_dragging_file = false;
static char drag_file_path[FAT32_MAX_PATH];
static int drag_icon_type = 0; 
static int drag_start_x = 0;
static int drag_start_y = 0;
static int drag_icon_orig_x = 0;
static int drag_icon_orig_y = 0;
static Window *drag_src_win = NULL;

// Windows array for z-order management
static Window *all_windows[32];
static int window_count = 0;

// Redraw system
static bool force_redraw = true;  
static uint32_t timer_ticks = 0;
static int desktop_refresh_timer = 0;

// Cursor state
static bool cursor_visible = true;
static int last_cursor_x = 400;
static int last_cursor_y = 300;

static bool periodic_refresh_pending = false;

// --- Desktop State ---
#define MAX_DESKTOP_ICONS 32
typedef struct {
    char name[64];
    int x, y;
    int type; 
} DesktopIcon;

static DesktopIcon desktop_icons[MAX_DESKTOP_ICONS];
static int desktop_icon_count = 0;

// Desktop Settings
bool desktop_snap_to_grid = true;
bool desktop_auto_align = true;
int desktop_max_rows_per_col = 13;
int desktop_max_cols = 23;

// Mouse Settings
int mouse_speed = 10;       
static int mouse_accum_x = 0;
static int mouse_accum_y = 0;

// Helper to check if string ends with suffix
static bool str_ends_with(const char *str, const char *suffix) {
    int str_len = 0; while(str[str_len]) str_len++;
    int suf_len = 0; while(suffix[suf_len]) suf_len++;
    if (suf_len > str_len) return false;
    
    for (int i = 0; i < suf_len; i++) {
        if (str[str_len - suf_len + i] != suffix[i]) return false;
    }
    return true;
}

// Helper to check if string starts with prefix
static bool str_starts_with(const char *str, const char *prefix) {
    while(*prefix) {
        if (*prefix++ != *str++) return false;
    }
    return true;
}


static void refresh_desktop_icons(void) {
    // Update limit in FS
    fat32_set_desktop_limit(desktop_max_cols * desktop_max_rows_per_col);

    FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(MAX_DESKTOP_ICONS * sizeof(FAT32_FileInfo));
    if (!files) return;

    int file_count = fat32_list_directory("/Desktop", files, MAX_DESKTOP_ICONS);
    
    // Temp array to hold new state
    DesktopIcon new_icons[MAX_DESKTOP_ICONS];
    int new_count = 0;
    bool file_processed[MAX_DESKTOP_ICONS];
    for(int i=0; i<MAX_DESKTOP_ICONS; i++) file_processed[i] = false;

    for (int i = 0; i < desktop_icon_count; i++) {
        int found_idx = -1;
        for (int j = 0; j < file_count; j++) {
            if (!file_processed[j] && str_eq(desktop_icons[i].name, files[j].name) != 0) {
                found_idx = j;
                break;
            }
        }
        
        if (found_idx != -1) {
            // Keep it
            if (new_count < MAX_DESKTOP_ICONS) {
                new_icons[new_count] = desktop_icons[i];
                new_count++;
                file_processed[found_idx] = true;
            }
        }
    }

    for (int i = 0; i < file_count; i++) {
        if (!file_processed[i]) {
            if (files[i].name[0] == '.') continue; 
            if (new_count >= MAX_DESKTOP_ICONS) break;

            DesktopIcon *dest = &new_icons[new_count];
            int k = 0; while(files[i].name[k] && k < 63) { dest->name[k] = files[i].name[k]; k++; }
            dest->name[k] = 0;

            if (files[i].is_directory) dest->type = 1;
            else if (str_ends_with(dest->name, ".shortcut")) dest->type = 2;
            else dest->type = 0;
            dest->x = -1; // Mark as new for layout
            dest->y = -1;
            
            new_count++;
        }
    }
    
    desktop_icon_count = new_count;
    for(int i=0; i<new_count; i++) desktop_icons[i] = new_icons[i];
    kfree(files);
    
    if (desktop_auto_align) {
        int start_x = 20;
        int start_y = 30;
        int grid_x = 0;
        int grid_y = 0;
        
        int recycle_idx = -1;
        for (int i = 0; i < desktop_icon_count; i++) {
            if (str_starts_with(desktop_icons[i].name, "Recycle Bin")) {
                recycle_idx = i;
                break;
            }
        }
        
        // Place Recycle Bin at bottom-right of grid
        if (recycle_idx != -1) {
            desktop_icons[recycle_idx].x = start_x + (desktop_max_cols - 1) * 80;
            desktop_icons[recycle_idx].y = start_y + (desktop_max_rows_per_col - 1) * 80;
        }
        
        for (int i = 0; i < desktop_icon_count; i++) {
            if (i == recycle_idx) continue;
            
            desktop_icons[i].x = start_x + (grid_x * 80);
            desktop_icons[i].y = start_y + (grid_y * 80);
            
            grid_y++;
            if (grid_y >= desktop_max_rows_per_col) {
                grid_y = 0;
                grid_x++;

            }
        }
    } else {
        // Place new icons in first available spot
        bool occupied[16][16] = {false};
        for (int i = 0; i < desktop_icon_count; i++) {
            if (desktop_icons[i].x != -1) {
                int col = (desktop_icons[i].x - 20) / 80;
                int row = (desktop_icons[i].y - 20) / 80;
                if (col >= 0 && col < 16 && row >= 0 && row < 16) occupied[col][row] = true;
            }
        }
        
        for (int i = 0; i < desktop_icon_count; i++) {
            if (desktop_icons[i].x == -1) {
                int found_col = -1, found_row = -1;
                for (int c = 0; c < 16; c++) {
                    for (int r = 0; r < desktop_max_rows_per_col; r++) {
                        if (!occupied[c][r]) {
                            found_col = c; found_row = r;
                            goto found;
                        }
                    }
                }
                found:
                if (found_col != -1) {
                    desktop_icons[i].x = 20 + found_col * 80;
                    desktop_icons[i].y = 20 + found_row * 80;
                    occupied[found_col][found_row] = true;
                }
            }
        }
    }
}

void wm_refresh_desktop(void) {
    refresh_desktop_icons();
    force_redraw = true;
}

static void create_desktop_shortcut(const char *app_name) {
    char path[128] = "/Desktop/";
    int p = 9;
    int n = 0; while(app_name[n]) path[p++] = app_name[n++];
    const char *ext = ".shortcut";
    int e = 0; while(ext[e]) path[p++] = ext[e++];
    path[p] = 0;
    
    FAT32_FileHandle *fh = fat32_open(path, "w");
    if (fh) fat32_close(fh);
    refresh_desktop_icons();
}

int wm_get_desktop_icon_count(void) {
    return desktop_icon_count;
}

void wm_show_message(const char *title, const char *message) {
    int i=0; while(title[i] && i<63) { msg_box_title[i] = title[i]; i++; } msg_box_title[i] = 0;
    i=0; while(message[i] && i<63) { msg_box_text[i] = message[i]; i++; } msg_box_text[i] = 0;
    msg_box_visible = true;
    force_redraw = true;
}

static void draw_icon_label(int x, int y, const char *label) {
    char line1[11] = {0}; // 10 chars + null
    char line2[11] = {0}; // 10 chars + null
    int len = 0; while(label[len]) len++;
    
    if (len <= 10) {
        for (int i = 0; i < len; i++) line1[i] = label[i];
    } else {
        // Dot-based wrap: keep extension together if prefix fits
        int dot_pos = -1;
        for (int i = len - 1; i >= 0; i--) {
            if (label[i] == '.') { dot_pos = i; break; }
        }

        int split = -1;
        if (dot_pos != -1 && dot_pos > 0 && dot_pos <= 10) {
            split = dot_pos;
        } else {
            // Word-based wrap: look for space in the first 11 characters
            for (int i = 10; i >= 0; i--) {
                if (label[i] == ' ') {
                    split = i;
                    break;
                }
            }
        }

        if (split != -1) {
            for (int i = 0; i < split; i++) line1[i] = label[i];
            int start2 = (label[split] == ' ') ? split + 1 : split;
            int j = 0;
            while (label[start2 + j] && j < 10) {
                line2[j] = label[start2 + j];
                j++;
            }
            if (label[start2 + j] != 0) {
                int t = (j > 8) ? 8 : j;
                line2[t] = '.'; line2[t+1] = '.'; line2[t+2] = 0;
            }
        } else {
            for (int i = 0; i < 10; i++) line1[i] = label[i];
            int j = 0;
            while (label[10 + j] && j < 10) {
                line2[j] = label[10 + j];
                j++;
            }
            if (label[10 + j] != 0) {
                int t = (j > 8) ? 8 : j;
                line2[t] = '.'; line2[t+1] = '.'; line2[t+2] = 0;
            }
        }
    }
    
    // Draw Line 1 Centered in 80px cell
    int l1_len = 0; while(line1[l1_len]) l1_len++;
    int l1_w = l1_len * 8;
    // x passed is cell left. Center is x + 40. Text start is x + 40 - w/2
    draw_string(x + (80 - l1_w)/2, y + 48, line1, COLOR_WHITE);
    
    // Draw Line 2 Centered
    if (line2[0]) {
        int l2_len = 0; while(line2[l2_len]) l2_len++;
        int l2_w = l2_len * 8;
        draw_string(x + (80 - l2_w)/2, y + 58, line2, COLOR_WHITE);
    }
}

// --- Drawing Helpers ---

void draw_bevel_rect(int x, int y, int w, int h, bool sunken) {
    draw_rect(x, y, w, h, COLOR_GRAY);
    
    uint32_t top_left = sunken ? COLOR_DKGRAY : COLOR_WHITE;
    uint32_t bot_right = sunken ? COLOR_WHITE : COLOR_DKGRAY;
    
    // Top
    draw_rect(x, y, w, 1, top_left);
    // Left
    draw_rect(x, y, 1, h, top_left);
    // Bottom
    draw_rect(x, y + h - 1, w, 1, bot_right);
    // Right
    draw_rect(x + w - 1, y, 1, h, bot_right);
}

void draw_button(int x, int y, int w, int h, const char *text, bool pressed) {
    draw_bevel_rect(x, y, w, h, pressed);
    // Center Text
    int len = 0; while(text[len]) len++;
    int tx = x + (w - (len * 8)) / 2;
    int ty = y + (h - 8) / 2;
    if (pressed) { tx++; ty++; }
    draw_string(tx, ty, text, COLOR_BLACK);
}

// Forward declarations for dock icons
static void draw_dock_files(int x, int y);
static void draw_dock_settings(int x, int y);
static void draw_dock_notepad(int x, int y);
static void draw_dock_calculator(int x, int y);
static void draw_dock_terminal(int x, int y);
static void draw_dock_minesweeper(int x, int y);
static void draw_dock_paint(int x, int y);
static void draw_dock_clock(int x, int y);
static void draw_dock_editor(int x, int y);
static void draw_filled_circle(int cx, int cy, int r, uint32_t color);

static void draw_scaled_icon(int x, int y, void (*draw_fn)(int, int)) {
    // 48x48 buffer for the dock icon
    uint32_t icon_buf[48 * 48];
    // Clear to magenta (transparent key color)
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    
    // Redirect graphics to our buffer
    graphics_set_render_target(icon_buf, 48, 48);
    // Draw at 0,0 in the buffer
    draw_fn(0, 0);
    // Restore graphics to screen
    graphics_set_render_target(NULL, 0, 0);
    
    // Calculate centered x,y in the 80x80 cell
    // (80-32)/2 = 24.
    int dx = x + 24, dy = y + 12;
    
    // Blit scaled down (nearest neighbor 48x48 -> 32x32 downsample, ratio = 1.5)
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) {
                put_pixel(dx + tx, dy + ty, c1);
            }
        }
    }
}

void draw_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    draw_rounded_rect_filled(0, 0, 48, 48, 10, 0xFFE0E0E0);
    draw_rounded_rect_filled(5, 5, 38, 38, 4, 0xFFFFFFFF);
    draw_rect(12, 15, 24, 2, 0xFFCCCCCC);
    draw_rect(12, 25, 24, 2, 0xFFCCCCCC);
    draw_rect(12, 35, 16, 2, 0xFFCCCCCC);
    
    graphics_set_render_target(NULL, 0, 0);
    
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    draw_icon_label(x, y, label);
}

void draw_folder_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_files);
    draw_icon_label(x, y, label);
}

void draw_document_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    // Document dock style (making the source drawing slightly smaller to reduce final size)
    draw_rounded_rect_filled(4, 4, 40, 40, 8, 0xFFFFFFFF);
    draw_rounded_rect_filled(8, 8, 32, 32, 4, 0xFFF5F5F5);
    draw_rect(14, 17, 20, 2, 0xFFBBBBBB);
    draw_rect(14, 25, 20, 2, 0xFFBBBBBB);
    draw_rect(14, 33, 14, 2, 0xFFBBBBBB);
    
    graphics_set_render_target(NULL, 0, 0);
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    draw_icon_label(x, y, label);
}

void draw_elf_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    // Grey squircle (macOS detailed style)
    draw_rounded_rect_filled(2, 2, 44, 44, 12, 0xFF353535); // Subtle shadow border
    draw_rounded_rect_filled(4, 4, 40, 40, 10, 0xFF4A4A4A); // Main grey body
    
    // Glossy top highlight
    draw_rect(10, 5, 28, 1, 0xFF5A5A5A);
    
    // Green "exec" text (fixed font 8x12)
    draw_string(8, 12, "exec", 0xFF00FF00);
    
    // Minor details to look "premium"
    draw_rect(10, 28, 28, 1, 0xFF3D3D3D);
    draw_rect(10, 34, 20, 1, 0xFF3D3D3D);
    
    graphics_set_render_target(NULL, 0, 0);
    
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    draw_icon_label(x, y, label);
}

// === Dynamic thumbnail cache for JPG explorer icons ===
#define THUMB_CACHE_SIZE 8
#define THUMB_PIXELS (48 * 48)
static struct {
    char path[FAT32_MAX_PATH];
    uint32_t pixels[THUMB_PIXELS];
    bool valid;
    bool failed; // Mark as failed so we don't retry
} thumb_cache[THUMB_CACHE_SIZE];
static int thumb_cache_next = 0; // Round-robin eviction

// Deferred Thumbnail Request Queue
#define THUMB_QUEUE_SIZE 16
static char thumb_request_queue[THUMB_QUEUE_SIZE][FAT32_MAX_PATH];
static int thumb_queue_head = 0;
static int thumb_queue_tail = 0;

static void thumb_request_push(const char *path) {
    if (!path) return;
    
    // Check if already in queue
    int curr = thumb_queue_head;
    while (curr != thumb_queue_tail) {
        if (str_eq(thumb_request_queue[curr], path) != 0) return;
        curr = (curr + 1) % THUMB_QUEUE_SIZE;
    }
    
    // Push if space
    int next_tail = (thumb_queue_tail + 1) % THUMB_QUEUE_SIZE;
    if (next_tail != thumb_queue_head) {
        int i = 0;
        while (path[i] && i < 255) {
            thumb_request_queue[thumb_queue_tail][i] = path[i];
            i++;
        }
        thumb_request_queue[thumb_queue_tail][i] = 0;
        thumb_queue_tail = next_tail;
    }
}

static bool thumb_cache_is_failed(const char *path) {
    for (int i = 0; i < THUMB_CACHE_SIZE; i++) {
        if (thumb_cache[i].failed && str_eq(thumb_cache[i].path, path) != 0) return true;
    }
    return false;
}

static uint32_t* thumb_cache_lookup(const char *path) {
    for (int i = 0; i < THUMB_CACHE_SIZE; i++) {
        if (thumb_cache[i].valid && str_eq(thumb_cache[i].path, path) != 0) {
            return thumb_cache[i].pixels;
        }
    }
    return NULL;
}



static uint32_t* thumb_cache_decode(const char *path) {
    // Open and read the JPG file
    FAT32_FileHandle *fh = fat32_open(path, "r");
    if (!fh) return NULL;
    
    uint32_t file_size = fh->size;
    if (file_size == 0 || file_size > 8 * 1024 * 1024) {
        fat32_close(fh);
        return NULL;
    }
    
    unsigned char *buf = (unsigned char*)kmalloc(file_size);
    if (!buf) { fat32_close(fh); return NULL; }
    
    int total = 0;
    while (total < (int)file_size) {
        int chunk = fat32_read(fh, buf + total, (int)file_size - total);
        if (chunk <= 0) break;
        total += chunk;
    }
    fat32_close(fh);
    
    if (total <= 0) { kfree(buf); return NULL; }
    
    // Decode JPEG
    njInit();
    if (njDecode(buf, total) != NJ_OK) {
        serial_write("[WM] njDecode failed for deferred thumb\n");
        njDone();
        kfree(buf);
        return NULL;
    }
    
    serial_write("[WM] njDecode OK for deferred thumb\n");
    
    int img_w = njGetWidth();
    int img_h = njGetHeight();
    unsigned char *img = njGetImage();
    
    // Store in cache — downscale to 48x48
    int slot = thumb_cache_next;
    thumb_cache_next = (thumb_cache_next + 1) % THUMB_CACHE_SIZE;
    
    // Copy path
    int p = 0;
    while (path[p] && p < 255) { thumb_cache[slot].path[p] = path[p]; p++; }
    thumb_cache[slot].path[p] = 0;
    
    // Downscale image to 48x48 with aspect-fill
    for (int ty = 0; ty < 48; ty++) {
        for (int tx = 0; tx < 48; tx++) {
            int sx = tx * img_w / 48;
            int sy = ty * img_h / 48;
            if (sx >= img_w) sx = img_w - 1;
            if (sy >= img_h) sy = img_h - 1;
            int idx = (sy * img_w + sx) * 3;
            uint32_t r = img[idx], g = img[idx+1], b = img[idx+2];
            thumb_cache[slot].pixels[ty * 48 + tx] = 0xFF000000 | (r << 16) | (g << 8) | b;
        }
    }
    
    thumb_cache[slot].valid = true;
    thumb_cache[slot].failed = false;
    
    njDone();
    kfree(buf);
    
    return thumb_cache[slot].pixels;
}

void draw_image_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    uint32_t *thumb = NULL;
    
    // Dynamic path: try thumbnail cache for any JPG file path
    if (!thumb_cache_is_failed(label)) {
        thumb = thumb_cache_lookup(label);
        if (!thumb) {
            // Queue for background decoding
            thumb_request_push(label);
        }
    }
    
    if (thumb) {
        // White border
        draw_rounded_rect_filled(0, 0, 48, 48, 4, 0xFFFFFFFF);
        // Draw thumbnail into icon - handle 48x48 dynamic thumbs
        int dst_w = 44, dst_h = 44;
        for (int ty = 0; ty < dst_h; ty++) {
            for (int tx = 0; tx < dst_w; tx++) {
                int sx = tx * 48 / dst_w;
                int sy = ty * 48 / dst_h;
                uint32_t pixel = thumb[sy * 48 + sx];
                put_pixel(2 + tx, 2 + ty, pixel);
            }
        }
    } else {
        // Fallback photo
        draw_rounded_rect_filled(0, 0, 48, 48, 10, 0xFFE0E0E0);
        draw_rounded_rect_filled(5, 5, 38, 38, 4, 0xFF87CEEB); // Sky
        draw_rect(5, 25, 38, 18, 0xFF90EE90); // Grass
        draw_filled_circle(15, 15, 6, 0xFFFFFF00); // Sun
    }
    
    graphics_set_render_target(NULL, 0, 0);
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    // Removing the explicit `draw_icon_label` call here to prevent double-text since `wm.c` or Explorer manually draws it as well inside their draw block
}

void draw_notepad_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_notepad);
    draw_icon_label(x, y, label);
}

void draw_calculator_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_calculator);
    draw_icon_label(x, y, label);
}

void draw_terminal_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_terminal);
    draw_icon_label(x, y, label);
}

void draw_minesweeper_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_minesweeper);
    draw_icon_label(x, y, label);
}

void draw_control_panel_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_settings);
    draw_icon_label(x, y, label);
}

void draw_clock_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_clock);
    draw_icon_label(x, y, label);
}

void draw_about_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    // About dock style
    draw_rounded_rect_filled(0, 0, 48, 48, 10, 0xFF4285F4);
    draw_rounded_rect_filled(5, 5, 38, 38, 4, 0xFFE8F0FE);
    draw_rect(22, 15, 4, 4, 0xFF4285F4); // Dot
    draw_rect(22, 23, 4, 16, 0xFF4285F4); // Body
    
    graphics_set_render_target(NULL, 0, 0);
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    draw_icon_label(x, y, label);
}

void draw_recycle_bin_icon(int x, int y, const char *label) {
    uint32_t icon_buf[48 * 48];
    for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
    graphics_set_render_target(icon_buf, 48, 48);
    
    // Recycle bin dock style
    draw_rounded_rect_filled(0, 0, 48, 48, 10, 0xFFECEFF1);
    draw_rounded_rect_filled(5, 5, 38, 38, 4, 0xFFCFD8DC);
    draw_rect(16, 18, 16, 20, 0xFF90A4AE); // Bin body
    draw_rect(12, 15, 24, 3, 0xFF78909C); // Bin lid
    draw_rect(20, 13, 8, 2, 0xFF78909C); // Handle
    
    graphics_set_render_target(NULL, 0, 0);
    int dx = x + 24, dy = y + 12;
    for (int ty = 0; ty < 32; ty++) {
        for (int tx = 0; tx < 32; tx++) {
            int src_x = tx * 48 / 32;
            int src_y = ty * 48 / 32;
            uint32_t c1 = icon_buf[src_y * 48 + src_x];
            if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
        }
    }
    
    draw_icon_label(x, y, label);
}

void draw_paint_icon(int x, int y, const char *label) {
    draw_scaled_icon(x, y, draw_dock_paint);
    draw_icon_label(x, y, label);
}

static void draw_filled_circle(int cx, int cy, int r, uint32_t color);

// Draw traffic light (close button - red)
void draw_traffic_light(int x, int y) {
    draw_filled_circle(x + 6, y + 6, 6, COLOR_TRAFFIC_RED);
    draw_filled_circle(x + 6, y + 6, 2, COLOR_WHITE);
}

// Draw a squircle-style app icon
void draw_squircle_icon(int x, int y, const char *label, uint32_t bg_color) {
    // Simplified squircle using rounded rectangle
    draw_rounded_rect_filled(x + 12, y, 56, 56, 12, bg_color);
    draw_icon_label(x, y + 60, label);
}

//  Files icon 
void draw_files_icon(int x, int y, const char *label) {
    draw_rounded_rect_filled(x + 27, y + 6, 25, 15, 3, 0xFF4A90E2);  // Blue color
    draw_squircle_icon(x, y, label, 0xFF4A90E2);
}

//  Settings/Gear icon
void draw_settings_icon(int x, int y, const char *label) {
    // Gear icon with dark background
    draw_squircle_icon(x, y, label, 0xFF666666);
    // Simple gear shape in the middle of squircle
    int cx = x + 12 + 28;
    int cy = y + 28;
    draw_rect(cx - 2, cy - 2, 4, 4, COLOR_WHITE);  // Center
}

static int isqrt_local(int n) {
    if (n <= 0) return 0;
    int x = n;
    int y = (x + 1) / 2;
    while (y < x) {
        x = y;
        y = (x + n / x) / 2;
    }
    return x;
}

static void draw_filled_circle(int cx, int cy, int r, uint32_t color) {
    for (int dy = -r; dy <= r; dy++) {
        int dx = isqrt_local(r * r - dy * dy);
        draw_rect(cx - dx, cy + dy, dx * 2 + 1, 1, color);
    }
}

static void draw_dock_files(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF1D5FAA);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF4A90E2);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF2E72C9);
    draw_rounded_rect_filled(x + 7, y + 13, 15, 7, 3, 0xFF62A8F5);
    draw_rounded_rect_filled(x + 8, y + 12, 13, 5, 3, 0xFF7DB8F8);
    draw_rounded_rect_filled(x + 5, y + 17, 38, 23, 5, 0xFFCDE4FA);
    draw_rounded_rect_filled(x + 7, y + 19, 34, 19, 4, 0xFFEAF5FF);
    draw_rect(x + 12, y + 23, 24, 2, 0xFF88B8D8);
    draw_rect(x + 12, y + 27, 17, 2, 0xFF88B8D8);
    draw_rect(x + 12, y + 31, 21, 2, 0xFF88B8D8);
}

static void draw_dock_settings(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF3A3A3A);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF6E6E6E);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF4A4A4A);
    int cx = x + 24, cy = y + 25;
    draw_rounded_rect_filled(cx - 4, cy - 18, 8, 7, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx - 4, cy + 11, 8, 7, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx - 18, cy - 4, 7, 8, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx + 11, cy - 4, 7, 8, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx - 14, cy - 14, 6, 6, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx + 8, cy - 14, 6, 6, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx - 14, cy + 8, 6, 6, 2, 0xFFCCCCCC);
    draw_rounded_rect_filled(cx + 8, cy + 8, 6, 6, 2, 0xFFCCCCCC);
    draw_filled_circle(cx, cy, 13, 0xFFCCCCCC);
    draw_filled_circle(cx, cy, 6, 0xFF4A4A4A);
    draw_filled_circle(cx, cy, 4, 0xFF3A3A3A);
}

static void draw_dock_notepad(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFCC9A00);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFFFFD700);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFFE8BC00);
    draw_rounded_rect_filled(x + 7, y + 9, 34, 32, 3, 0xFFFFFDE7);
    draw_rounded_rect_filled(x + 7, y + 9, 34, 8, 3, 0xFFFFCA28);
    draw_rect(x + 7, y + 13, 34, 4, 0xFFFFCA28);
    draw_rect(x + 11, y + 21, 18, 2, 0xFFBBAA70);
    draw_rect(x + 11, y + 25, 26, 1, 0xFFCCBB88);
    draw_rect(x + 11, y + 28, 22, 1, 0xFFCCBB88);
    draw_rect(x + 11, y + 31, 24, 1, 0xFFCCBB88);
    draw_rect(x + 11, y + 34, 18, 1, 0xFFCCBB88);
    draw_rect(x + 32, y + 11, 3, 13, 0xFFF5DEB3);
    draw_rect(x + 32, y + 9, 3, 4, 0xFFFF9800);
    draw_rect(x + 33, y + 24, 1, 2, 0xFF555555);
}

static void draw_dock_calculator(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF111111);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF222222);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF151515);
    draw_rounded_rect_filled(x + 6, y + 6, 36, 11, 3, 0xFF1A3A2A);
    draw_rect(x + 25, y + 9, 14, 5, 0xFF33FF88);
    // 3x3 button grid
    uint32_t btn_clr[3][3] = {
        {0xFF555555, 0xFF555555, 0xFF555555},
        {0xFF444444, 0xFF444444, 0xFF444444},
        {0xFF444444, 0xFF444444, 0xFFFF9500},
    };
    for (int row = 0; row < 3; row++) {
        for (int col = 0; col < 3; col++) {
            draw_rounded_rect_filled(x + 10 + col * 9, y + 22 + row * 6, 7, 5, 2, btn_clr[row][col]);
        }
    }
}

static void draw_dock_terminal(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF0A0A0A);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF161616);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF0D0D0D);
    int px = x + 12;
    int py = y + 24;
    for (int i = 0; i < 6; i++) {
        draw_rect(px + i, py - 4 + i, 2, 1, 0xFF33DD33);
    }
    for (int i = 0; i < 6; i++) {
        draw_rect(px + i, py + 4 - i, 2, 1, 0xFF33DD33);
    }
    draw_rect(px + 10, py + 7, 8, 1, 0xFF33DD33);
}

static void draw_dock_minesweeper(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF1B5E20);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF4CAF50);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF388E3C);
    for (int row = 0; row < 5; row++) {
        for (int col = 0; col < 5; col++) {
            int bx = x + 6 + col * 8, by = y + 7 + row * 8;
            if ((row == 2 && col == 2)) {
                draw_rounded_rect_filled(bx, by, 6, 6, 1, 0xFFC8E6C9);
            } else if ((row + col) % 2 == 0) {
                draw_rounded_rect_filled(bx, by, 6, 6, 1, 0xFF81C784);
                draw_rect(bx, by, 6, 1, 0xFFA5D6A7);
                draw_rect(bx, by, 1, 6, 0xFFA5D6A7);
                draw_rect(bx + 5, by + 1, 1, 5, 0xFF2E7D32);
                draw_rect(bx + 1, by + 5, 5, 1, 0xFF2E7D32);
            } else {
                draw_rounded_rect_filled(bx, by, 6, 6, 1, 0xFF66BB6A);
                draw_rect(bx, by, 6, 1, 0xFF81C784);
                draw_rect(bx, by, 1, 6, 0xFF81C784);
            }
        }
    }
    int mx = x + 6 + 2 * 8 + 3, my = y + 7 + 2 * 8 + 3;
    draw_filled_circle(mx, my, 4, 0xFF111111);
    draw_rect(mx - 5, my - 1, 11, 2, 0xFF111111);
    draw_rect(mx - 1, my - 5, 2, 11, 0xFF111111);
    draw_rect(mx - 3, my - 3, 2, 2, 0xFF111111);
    draw_rect(mx + 1, my - 3, 2, 2, 0xFF111111);
    draw_rect(mx - 3, my + 1, 2, 2, 0xFF111111);
    draw_rect(mx + 1, my + 1, 2, 2, 0xFF111111);
    draw_rect(mx - 1, my - 2, 2, 2, 0xFFFFFFFF);
    draw_rect(x + 7, y + 40, 1, 6, 0xFF333333);
    draw_rect(x + 8, y + 40, 4, 3, 0xFFFF3333);
}

static void draw_dock_paint(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFBBBBBB);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFFFFFFFF);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFFEEEEEE);
    draw_rounded_rect_filled(x + 6, y + 9, 36, 30, 10, 0xFFEEDDB0);
    draw_rounded_rect_filled(x + 8, y + 11, 32, 26, 8, 0xFFF5E8C0);
    draw_filled_circle(x + 35, y + 32, 5, 0xFFEEDDB0);
    draw_filled_circle(x + 35, y + 32, 3, 0xFFFFFFFF);
    draw_filled_circle(x + 15, y + 18, 5, 0xFFFF3333);
    draw_filled_circle(x + 23, y + 14, 5, 0xFF3399FF);
    draw_filled_circle(x + 31, y + 18, 5, 0xFFFFCC00);
    draw_filled_circle(x + 28, y + 27, 5, 0xFF33CC33);
    draw_filled_circle(x + 16, y + 27, 5, 0xFFFF6600);
    draw_rect(x + 30, y + 30, 3, 14, 0xFF8B6914);
    draw_rounded_rect_filled(x + 29, y + 27, 5, 5, 2, 0xFFBBBBBB);
    draw_rounded_rect_filled(x + 30, y + 22, 3, 7, 1, 0xFF1A1A1A);
}

static void draw_dock_clock(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF4A4A4A);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF6E6E6E);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF5A5A5A);
    
    int cx = x + 24, cy = y + 24;
    draw_filled_circle(cx, cy, 18, 0xFFF0F0F0);
    draw_filled_circle(cx, cy, 1, 0xFF333333);
    
    // Hour hand
    draw_rect(cx - 1, cy - 8, 2, 8, 0xFF333333);
    // Minute hand
    draw_rect(cx, cy - 1, 10, 2, 0xFF333333);
}

static void draw_dock_editor(int x, int y) {
    draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF0A1628);
    draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF1565C0);
    draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF0D47A1);
    draw_rect(x + 5, y + 8, 9, 32, 0xFF1A237E);
    draw_filled_circle(x + 10, y + 14, 2, 0xFF7986CB);
    draw_filled_circle(x + 10, y + 22, 2, 0xFF7986CB);
    draw_filled_circle(x + 10, y + 30, 2, 0xFF7986CB);
    draw_rect(x + 15, y + 8, 28, 32, 0xFF1B2B3C);
    draw_rect(x + 15, y + 8, 14, 5, 0xFF1B2B3C);
    draw_rect(x + 15, y + 8, 14, 1, 0xFF569CD6);
    draw_rect(x + 18, y + 13, 9, 2, 0xFF569CD6);
    draw_rect(x + 29, y + 13, 8, 2, 0xFF4EC9B0);
    draw_rect(x + 18, y + 18, 5, 2, 0xFFCE9178);
    draw_rect(x + 25, y + 18, 7, 2, 0xFFCE9178);
    draw_rect(x + 21, y + 23, 7, 2, 0xFF9CDCFE);
    draw_rect(x + 30, y + 23, 5, 2, 0xFFD4D4D4);
    draw_rect(x + 18, y + 28, 16, 2, 0xFF6A9955);
    draw_rect(x + 18, y + 33, 10, 2, 0xFFD4D4D4);
    draw_rect(x + 30, y + 33, 6, 2, 0xFF569CD6);
}

void draw_window(Window *win) {
    if (!win->visible) return;
    
    // Dark mode window with rounded corners
    // Border/Shadow effect
    draw_rounded_rect_filled(win->x - 1, win->y - 1, win->w + 2, win->h + 2, 8, 0xFF000000);
    
    // Main window body (fully rounded)
    draw_rounded_rect_filled(win->x, win->y, win->w, win->h, 8, COLOR_DARK_PANEL);
    
    // Title Bar (rounded at top only - overdraw bottom to hide rounding)
    draw_rounded_rect_filled(win->x, win->y, win->w, 20, 8, COLOR_DARK_TITLEBAR);
    draw_rect(win->x, win->y + 12, win->w, 8, COLOR_DARK_TITLEBAR);  // Cover bottom rounded corners
    draw_string(win->x + 28, win->y + 5, win->title, COLOR_DARK_TEXT);
    
    // Traffic Light (close button - red)
    draw_traffic_light(win->x + 8, win->y + 2);
    
    // Client Area with dark background, rounded only at bottom
    draw_rounded_rect_filled(win->x, win->y + 20, win->w, win->h - 20, 8, COLOR_DARK_BG);
    draw_rect(win->x, win->y + 20, win->w, 8, COLOR_DARK_BG);
    
    if (win->comp_pixels) {
        graphics_blit_buffer(win->comp_pixels, win->x, win->y + 20, win->w, win->h - 20);
    } else if (win->pixels) {
        graphics_blit_buffer(win->pixels, win->x, win->y + 20, win->w, win->h - 20);
    }
    
    if (win->paint) {
        win->paint(win);
    }
}

// Draw Mouse Cursor (Simple Arrow)
void draw_cursor(int x, int y) {
    // 0 = Transparent (skip), 1 = Black, 2 = White
    static const uint8_t cursor_bitmap[10][10] = {
        {1,1,0,0,0,0,0,0,0,0},
        {1,2,1,0,0,0,0,0,0,0},
        {1,2,2,1,0,0,0,0,0,0},
        {1,2,2,2,1,0,0,0,0,0},
        {1,2,2,2,2,1,0,0,0,0},
        {1,2,2,2,2,2,1,0,0,0},
        {1,2,2,1,1,1,1,0,0,0},
        {1,1,1,0,1,2,1,0,0,0},
        {0,0,0,0,0,1,2,1,0,0},
        {0,0,0,0,0,0,1,0,0,0}
    };
    
    for (int r = 0; r < 10; r++) {
        for (int c = 0; c < 10; c++) {
            uint8_t p = cursor_bitmap[r][c];
            if (p == 1) put_pixel(x + c, y + r, COLOR_BLACK);
            else if (p == 2) put_pixel(x + c, y + r, COLOR_WHITE);
        }
    }
}

// Erase cursor by redrawing the background in that area
static void erase_cursor(int x, int y) {
    int sw = get_screen_width();
    int sh = get_screen_height();
    
    // Clamp to screen
    int x1 = x < 0 ? 0 : x;
    int y1 = y < 0 ? 0 : y;
    int x2 = x + 10 > sw ? sw : x + 10;
    int y2 = y + 10 > sh ? sh : y + 10;
    int w = x2 - x1;
    int h = y2 - y1;
    
    if (y1 < sh - 28) {
        draw_rect(x1, y1, w, h, COLOR_TEAL);
    } else {
        draw_rect(x1, y1, w, h, COLOR_GRAY);
    }
}

// --- Clock ---
static uint8_t rtc_read(uint8_t reg) {
    outb(0x70, reg);
    return inb(0x71);
}

static void draw_clock(int x, int y) {
    while (rtc_read(0x0A) & 0x80);

    uint8_t s = rtc_read(0x00);
    uint8_t m = rtc_read(0x02);
    uint8_t h = rtc_read(0x04);
    uint8_t b = rtc_read(0x0B);

    if (!(b & 0x04)) {
        s = (s & 0x0F) + ((s >> 4) * 10);
        m = (m & 0x0F) + ((m >> 4) * 10);
        h = (h & 0x0F) + ((h >> 4) * 10);
    }

    char buf[9];
    buf[0] = '0' + (h / 10);
    buf[1] = '0' + (h % 10);
    buf[2] = ':';
    buf[3] = '0' + (m / 10);
    buf[4] = '0' + (m % 10);
    buf[5] = ':';
    buf[6] = '0' + (s / 10);
    buf[7] = '0' + (s % 10);
    buf[8] = 0;

    draw_string(x, y, buf, COLOR_WHITE);
}

// --- Main Paint Function ---
void wm_paint(void) {
    int sw = get_screen_width();
    int sh = get_screen_height();
    
    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));

    DirtyRect dirty = graphics_get_dirty_rect();
    if (dirty.active) {
        graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
    } else {
        graphics_clear_clipping();
    }

    // 1. Desktop Background (respects wallpaper color/pattern)
    draw_desktop_background();
    
    // Draw Desktop Icons
    for (int i = 0; i < desktop_icon_count; i++) {
        DesktopIcon *icon = &desktop_icons[i];
        if (dirty.active) {
            if (icon->x + 80 <= dirty.x || icon->x >= dirty.x + dirty.w ||
                icon->y + 80 <= dirty.y || icon->y >= dirty.y + dirty.h) {
                continue;
            }
        }
        if (icon->type == 1) draw_folder_icon(icon->x, icon->y, icon->name);
        else if (icon->type == 2) {
            // App icon - strip .shortcut for display
            char label[64];
            int len = 0;
            while(icon->name[len] && len < 63) { label[len] = icon->name[len]; len++; }
            label[len] = 0;
            if (len > 9 && str_ends_with(label, ".shortcut")) {
                label[len-9] = 0;
            }
            
            if (str_starts_with(icon->name, "Notepad")) draw_notepad_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Calculator")) draw_calculator_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Terminal")) draw_terminal_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Minesweeper")) draw_minesweeper_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Settings")) draw_control_panel_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Clock")) draw_clock_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "About")) draw_about_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Recycle Bin")) draw_recycle_bin_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Files")) draw_folder_icon(icon->x, icon->y, label);
            else if (str_starts_with(icon->name, "Paint")) draw_paint_icon(icon->x, icon->y, label);
            else draw_icon(icon->x, icon->y, label);
        } else {
            if (str_ends_with(icon->name, ".elf")) draw_elf_icon(icon->x, icon->y, icon->name);
            else if (str_ends_with(icon->name, ".pnt")) draw_paint_icon(icon->x, icon->y, icon->name);
            else if (str_ends_with(icon->name, ".jpg") || str_ends_with(icon->name, ".JPG")) {
                char full_path[128] = "/Desktop/";
                int p=9; int n=0; while(icon->name[n] && p < 127) full_path[p++] = icon->name[n++]; full_path[p]=0;
                draw_image_icon(icon->x, icon->y, full_path);
                draw_icon_label(icon->x, icon->y, icon->name);
            }
            else draw_document_icon(icon->x, icon->y, icon->name);
        }
    }
    
    // 3. Windows - sort by z-index and draw
    Window *sorted_windows[32];
    for (int i = 0; i < window_count; i++) {
        sorted_windows[i] = all_windows[i];
    }
    
    for (int i = 0; i < window_count - 1; i++) {
        for (int j = 0; j < window_count - i - 1; j++) {
            if (sorted_windows[j]->z_index > sorted_windows[j + 1]->z_index) {
                Window *temp = sorted_windows[j];
                sorted_windows[j] = sorted_windows[j + 1];
                sorted_windows[j + 1] = temp;
            }
        }
    }
    
    for (int i = 0; i < window_count; i++) {
        Window *win = sorted_windows[i];
        if (!win->visible) continue;

        if (dirty.active && !win->focused) {
            if (win->x + win->w <= dirty.x || win->x >= dirty.x + dirty.w ||
                win->y + win->h <= dirty.y || win->y >= dirty.y + dirty.h) {
                continue;
            }
        }
        draw_window(win);
    }
    
    draw_rect(0, 0, sw, 30, COLOR_TOPBAR_BG);
    draw_boredos_logo(8, 8, 1);
    draw_clock(sw - 80, 12);
    
    if (start_menu_open) {
        int menu_h = 85;
        draw_rounded_rect_filled(8, 40, 160, menu_h, 8, COLOR_DARK_PANEL);
        draw_string(20, 48, "About BoredOS", COLOR_DARK_TEXT);
        draw_string(20, 68, "Settings", COLOR_DARK_TEXT);
        draw_string(20, 88, "Shutdown", COLOR_DARK_TEXT);
        draw_string(20, 108, "Restart", COLOR_DARK_TEXT);
    }
    
    int dock_h = 60;
    int dock_y = sh - dock_h - 6;   
    int dock_item_size = 48;
    int dock_spacing = 10;
    int total_dock_width = 8 * (dock_item_size + dock_spacing);
    int dock_bg_x = (sw - total_dock_width) / 2 - 12;   
    int dock_bg_w = total_dock_width + 24;
    draw_rounded_rect_filled(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG);
    
    int dock_x = (sw - total_dock_width) / 2;
    int dock_item_y = dock_y + 6;
    
    draw_dock_files(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_settings(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_notepad(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_calculator(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_terminal(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_minesweeper(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_paint(dock_x, dock_item_y);
    dock_x += dock_item_size + dock_spacing;
    draw_dock_clock(dock_x, dock_item_y);
    // Editor removed from dock
    
    // Desktop Context Menu (with rounded corners)
    if (desktop_menu_visible) {
        int menu_w = 140;
        int item_h = 25;
        int menu_h = (desktop_menu_target_icon != -1) ? 125 : 75;
        
        draw_rounded_rect_filled(desktop_menu_x, desktop_menu_y, menu_w, menu_h, 8, COLOR_DARK_PANEL);
        
        if (desktop_menu_target_icon != -1) {
            bool can_paste = explorer_clipboard_has_content();
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5, "Cut", COLOR_WHITE);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h, "Copy", COLOR_WHITE);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_WHITE : COLOR_DKGRAY);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 3, "Delete", COLOR_TRAFFIC_RED);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 4, "Rename", COLOR_WHITE);
        } else {
            bool can_paste = explorer_clipboard_has_content();
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5, "New File", COLOR_WHITE);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h, "New Folder", COLOR_WHITE);
            draw_string(desktop_menu_x + 10, desktop_menu_y + 5 + item_h * 2, "Paste", can_paste ? COLOR_WHITE : COLOR_DKGRAY);
        }
    }

    // Desktop Dialogs (dark mode)
    if (desktop_dialog_state != 0) {
        int dlg_w = 300; int dlg_h = 110;
        int dlg_x = (sw - dlg_w) / 2;
        int dlg_y = (sh - dlg_h) / 2;
        
        draw_rounded_rect_filled(dlg_x, dlg_y, dlg_w, dlg_h, 8, COLOR_DARK_PANEL);
        
        const char *title = "Rename";
        const char *btn_text = "Rename";
        if (desktop_dialog_state == 1) { title = "Create New File"; btn_text = "Create"; }
        else if (desktop_dialog_state == 2) { title = "Create New Folder"; btn_text = "Create"; }
        
        draw_string(dlg_x + 10, dlg_y + 10, title, COLOR_WHITE);
        draw_rounded_rect_filled(dlg_x + 10, dlg_y + 35, 280, 20, 4, COLOR_DARK_BG);
        draw_string(dlg_x + 15, dlg_y + 40, desktop_dialog_input, COLOR_WHITE);
        // Cursor
        draw_rect(dlg_x + 15 + desktop_dialog_cursor * 8, dlg_y + 39, 2, 12, COLOR_WHITE);
        
        draw_rounded_rect_filled(dlg_x + 50, dlg_y + 65, 80, 25, 4, COLOR_DARK_BORDER);
        draw_string(dlg_x + 70, dlg_y + 72, btn_text, COLOR_WHITE);
        
        draw_rounded_rect_filled(dlg_x + 170, dlg_y + 65, 80, 25, 4, COLOR_DARK_BORDER);
        draw_string(dlg_x + 185, dlg_y + 72, "Cancel", COLOR_WHITE);
    }
    
    // Message Box (dark mode)
    if (msg_box_visible) {
        int mw = 320;
        int mh = 100;
        int mx = (sw - mw) / 2;
        int my = (sh - mh) / 2;
        
        draw_rounded_rect_filled(mx, my, mw, mh, 8, COLOR_DARK_PANEL);
        draw_string(mx + 15, my + 10, msg_box_title, COLOR_DARK_TEXT);
        draw_string(mx + 10, my + 40, msg_box_text, COLOR_DARK_TEXT);
        draw_rounded_rect_filled(mx + mw/2 - 30, my + 70, 60, 20, 4, COLOR_DARK_BORDER);
        draw_string(mx + mw/2 - 18, my + 75, "OK", COLOR_DARK_TEXT);
    }
    
    // Custom Overlay (VM Graphics)
    if (wm_custom_paint_hook) {
        wm_custom_paint_hook();
    }
    
    // Draw Dragged Icon
    if (is_dragging_file) {
        if (drag_icon_type == 1) draw_folder_icon(mx - 20, my - 20, "Moving...");
        else if (drag_icon_type == 2) draw_icon(mx - 20, my - 20, "Moving...");
        else draw_document_icon(mx - 20, my - 20, "Moving...");
    }
    
    // 7. Mouse cursor (draw last so it's on top)
    draw_cursor(mx, my);
    last_cursor_x = mx;
    last_cursor_y = my;
    
    // Flip the buffer - display the rendered frame atomically
    graphics_flip_buffer();

    // Restore IRQs
    asm volatile("push %0; popfq" : : "r"(rflags));
}

// --- Input Handling ---

bool rect_contains(int x, int y, int w, int h, int px, int py) {
    return px >= x && px < x + w && py >= y && py < y + h;
}

void wm_bring_to_front(Window *win) {
    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
    // Clear focus from all windows
    for (int i = 0; i < window_count; i++) {
        all_windows[i]->focused = false;
    }
    
    // Find current max z-index
    int max_z = 0;
    for (int i = 0; i < window_count; i++) {
        if (all_windows[i]->z_index > max_z) max_z = all_windows[i]->z_index;
    }
    
    win->visible = true;
    win->focused = true;
    win->z_index = max_z + 1;
    force_redraw = true;
    asm volatile("push %0; popfq" : : "r"(rflags));
}

void wm_add_window(Window *win) {
    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
    if (window_count < 32) {
        all_windows[window_count++] = win;
        wm_bring_to_front(win); // Ensure newly added windows are on top
    }
    asm volatile("push %0; popfq" : : "r"(rflags));
}

Window* wm_find_window_by_title(const char *title) {
    if (!title) return NULL;
    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
    for (int i = 0; i < window_count; i++) {
        if (all_windows[i] && all_windows[i]->title && str_eq(all_windows[i]->title, title)) {
            asm volatile("push %0; popfq" : : "r"(rflags));
            return all_windows[i];
        }
    }
    asm volatile("push %0; popfq" : : "r"(rflags));
    return NULL;
}

void wm_remove_window(Window *win) {
    if (!win) return;
    
    serial_write("WM: Removing window '");
    if (win->title) serial_write(win->title);
    else serial_write("unknown");
    serial_write("'\n");
    
    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
    
    int index = -1;
    for (int i = 0; i < window_count; i++) {
        if (all_windows[i] == win) {
            index = i;
            break;
        }
    }
    
    if (index != -1) {
        // Shift remaining windows
        for (int i = index; i < window_count - 1; i++) {
            all_windows[i] = all_windows[i + 1];
        }
        window_count--;
        
        // Mark for redraw while protected
        force_redraw = true;
    } else {
        asm volatile("push %0; popfq" : : "r"(rflags));
        serial_write("WM: Window not found in all_windows list!\n");
        return;
    }
    
    if (win->pixels) kfree(win->pixels);
    if (win->comp_pixels) kfree(win->comp_pixels);
    if (win->title && win->handle_close) { 
        kfree(win->title);
    }
    kfree(win);
    
    asm volatile("push %0; popfq" : : "r"(rflags));
}

void wm_handle_click(int x, int y) {
    int sh = get_screen_height();
    int sw = get_screen_width();
    
    if (msg_box_visible) {
        int mw = 320;
        int mh = 100;
        int mx = (sw - mw) / 2;
        int my = (sh - mh) / 2;
        if (rect_contains(mx + mw/2 - 30, my + 70, 60, 20, x, y)) {
            msg_box_visible = false;
            force_redraw = true;
        }
        return;
    }
    
    // Handle Desktop Context Menu Click
    if (desktop_menu_visible) {
        int menu_w = 140;
        int menu_h = (desktop_menu_target_icon != -1) ? 125 : 75;
        
        if (rect_contains(desktop_menu_x, desktop_menu_y, menu_w, menu_h, x, y)) {
            int rel_y = y - desktop_menu_y;
            int item = rel_y / 25;
            
            if (item == 0 && desktop_menu_target_icon != -1) { // Cut
                DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
                char path[128] = "/Desktop/";
                int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                explorer_clipboard_cut(path);
            } else if (item == 1 && desktop_menu_target_icon != -1) { // Copy
                DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
                char path[128] = "/Desktop/";
                int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                explorer_clipboard_copy(path);
            } else if (item == 0 && desktop_menu_target_icon == -1) { // New File
                desktop_dialog_state = 1;
                desktop_dialog_input[0] = 0;
                desktop_dialog_cursor = 0;
            } else if (item == 1 && desktop_menu_target_icon == -1) { // New Folder
                desktop_dialog_state = 2;
                desktop_dialog_input[0] = 0;
                desktop_dialog_cursor = 0;
            } else if (item == 2) { // Paste
                bool can_paste = explorer_clipboard_has_content();
                if (desktop_menu_target_icon != -1) {
                    DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
                    if (icon->type != 1) can_paste = false;
                }
                
                if (can_paste) {
                    int old_count = desktop_icon_count;
                    if (desktop_menu_target_icon != -1 && desktop_icons[desktop_menu_target_icon].type == 1) {
                        // Paste into folder
                        char path[128] = "/Desktop/";
                        DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
                        int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                        explorer_clipboard_paste(&win_explorer, path);
                    } else {
                        // Paste to desktop
                        explorer_clipboard_paste(&win_explorer, "/Desktop");
                    }
                    refresh_desktop_icons();

                    if (!desktop_auto_align && desktop_icon_count > old_count && desktop_menu_target_icon == -1) {
                        int new_idx = desktop_icon_count - 1;
                        desktop_icons[new_idx].x = desktop_menu_x - 20;
                        desktop_icons[new_idx].y = desktop_menu_y - 20;
                        if (desktop_snap_to_grid) {
                            int col = (desktop_icons[new_idx].x - 20 + 40) / 80;
                            int row = (desktop_icons[new_idx].y - 20 + 40) / 80;
                            if (col < 0) col = 0; if (row < 0) row = 0;
                            desktop_icons[new_idx].x = 20 + col * 80;
                            desktop_icons[new_idx].y = 20 + row * 80;
                        }
                    }
                }
            }
            else if (item == 3 && desktop_menu_target_icon != -1) { // Delete
                DesktopIcon *icon = &desktop_icons[desktop_menu_target_icon];
                char path[128] = "/Desktop/";
                int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                explorer_delete_recursive(path);
                refresh_desktop_icons();
            }
            else if (item == 4 && desktop_menu_target_icon != -1) { // Rename
                desktop_dialog_state = 8;
                desktop_dialog_target = desktop_menu_target_icon;
                int k=0; while(desktop_icons[desktop_dialog_target].name[k]) {
                    desktop_dialog_input[k] = desktop_icons[desktop_dialog_target].name[k];
                    k++;
                }
                desktop_dialog_input[k] = 0;
                desktop_dialog_cursor = k;
            }
        }
        desktop_menu_visible = false;
        force_redraw = true;
        return;
    }

    // Handle Desktop Dialog Clicks
    if (desktop_dialog_state != 0) {
        int dlg_x = (sw - 300) / 2; int dlg_y = (sh - 110) / 2;
        if (rect_contains(dlg_x + 50, dlg_y + 65, 80, 25, x, y)) { // Confirm
            if (desktop_dialog_state == 8) { // Rename
                char old_path[128] = "/Desktop/";
                char new_path[128] = "/Desktop/";
                int p=9; int n=0; while(desktop_icons[desktop_dialog_target].name[n]) old_path[p++] = desktop_icons[desktop_dialog_target].name[n++]; old_path[p]=0;
                p=9; n=0; while(desktop_dialog_input[n]) new_path[p++] = desktop_dialog_input[n++]; new_path[p]=0;
                
                if (fat32_rename(old_path, new_path)) {
                    refresh_desktop_icons();
                    explorer_refresh_all();
                }
            } else if (desktop_dialog_state == 1 || desktop_dialog_state == 2) { // Create File/Folder
                if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) {
                    wm_show_message("Error", "Desktop is full!");
                } else if (desktop_dialog_input[0] != 0) {
                    char path[128] = "/Desktop/";
                    int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0;
                    if (desktop_dialog_state == 1) {
                        FAT32_FileHandle *fh = fat32_open(path, "w");
                        if (fh) fat32_close(fh);
                    } else {
                        fat32_mkdir(path);
                    }
                    refresh_desktop_icons();
                    explorer_refresh_all();
                }
            }
            desktop_dialog_state = 0;
            force_redraw = true;
            return;
        }
        if (rect_contains(dlg_x + 170, dlg_y + 65, 80, 25, x, y)) { // Cancel
            desktop_dialog_state = 0;
            force_redraw = true;
            return;
        }
        if (rect_contains(dlg_x + 10, dlg_y + 35, 280, 20, x, y)) {
            desktop_dialog_cursor = (x - dlg_x - 15) / 8;
            int len = 0; while(desktop_dialog_input[len]) len++;
            if (desktop_dialog_cursor > len) desktop_dialog_cursor = len;
            force_redraw = true;
            return;
        }
    }
    
    // Check Top Bar Logo (toggle dropdown menu)
    if (rect_contains(8, 8, 24, 24, x, y)) {
        start_menu_open = !start_menu_open;
        force_redraw = true;
        pending_desktop_icon_click = -1;
        return;
    }
    
    // Handle top bar dropdown menu items
    if (start_menu_open && rect_contains(8, 40, 160, 120, x, y)) {
        int rel_y = y - 40;
        int item = rel_y / 20;
        
        if (item == 0) {  // About
            process_create_elf("/bin/about.elf", NULL);
        } else if (item == 1) {  // Settings
            Window *existing = wm_find_window_by_title("Settings");
            if (existing) wm_bring_to_front(existing);
            else process_create_elf("/bin/settings.elf", NULL);
        } else if (item == 2) {  // Shutdown
            k_shutdown();
        } else if (item == 3) {  // Restart
            k_reboot();
        }
        
        start_menu_open = false;
        force_redraw = true;
        return;
    }
    
    // Find topmost window at click location
    Window *topmost = NULL;
    int topmost_z = -1;
    
    for (int i = 0; i < window_count; i++) {
        Window *win = all_windows[i];
        if (win->visible && rect_contains(win->x, win->y, win->w, win->h, x, y)) {
            if (win->z_index > topmost_z) {
                topmost = win;
                topmost_z = win->z_index;
            }
        }
    }
    
    // If a window was clicked
    if (topmost != NULL) {
        wm_bring_to_front(topmost);
        
        // Check traffic light close button (now at top-left)
        if (rect_contains(topmost->x + 8, topmost->y + 2, 12, 12, x, y)) {
            if (topmost->handle_close) {
                topmost->handle_close(topmost);
            } else {
                topmost->visible = false;
            }
            
            // Reset window state on close
            if (topmost == &win_explorer) {
                explorer_reset();
            }
        } else if (y < topmost->y + 30) {
            // Dragging the title bar
            is_dragging = true;
            drag_window = topmost;
            drag_offset_x = x - topmost->x;
            drag_offset_y = y - topmost->y;
        } else {
            // Content click
            if (topmost->handle_click) {
                topmost->handle_click(topmost, x - topmost->x, y - topmost->y - 20);
            }
        }
        pending_desktop_icon_click = -1;
    } else {
        // No window clicked - check desktop icons
        // Clear focus from all windows first
        for (int w = 0; w < window_count; w++) {
            all_windows[w]->focused = false;
        }
        
        pending_desktop_icon_click = -1;
        
        for (int i = 0; i < desktop_icon_count; i++) {
            DesktopIcon *icon = &desktop_icons[i];
            if (rect_contains(icon->x + 20, icon->y, 40, 40, x, y)) {
                // Handle click - Defer to mouse up to allow dragging
                pending_desktop_icon_click = i;
                return;
            }
        }
    }
    
    // Close dropdown menu if clicked elsewhere
    if (start_menu_open) {
        start_menu_open = false;
    }
    
    force_redraw = true;
}

// Handle right click (context menu or special actions)
void wm_handle_right_click(int x, int y) {
    desktop_menu_visible = false; // Close if open
    // Find topmost window at click location
    Window *topmost = NULL;
    int topmost_z = -1;
    
    for (int i = 0; i < window_count; i++) {
        Window *win = all_windows[i];
        if (win->visible && rect_contains(win->x, win->y, win->w, win->h, x, y)) {
            if (win->z_index > topmost_z) {
                topmost = win;
                topmost_z = win->z_index;
            }
        }
    }
    
    // If a window was clicked
    if (topmost != NULL) {
        // Don't process close button or title bar for right click
        if (y >= topmost->y + 20) {
            // Content right click
            if (topmost->handle_right_click) {
                topmost->handle_right_click(topmost, x - topmost->x, y - topmost->y - 20);
            }
        }
    } else {
        // Desktop Right Click
        desktop_menu_visible = true;
        desktop_menu_x = x;
        desktop_menu_y = y;
        desktop_menu_target_icon = -1;
        
        // Check if clicked on an icon
        for (int i = 0; i < desktop_icon_count; i++) {
            if (rect_contains(desktop_icons[i].x + 20, desktop_icons[i].y, 40, 40, x, y)) {
                desktop_menu_target_icon = i;
                break;
            }
        }
    }
    
    force_redraw = true;
}void wm_handle_mouse(int dx, int dy, uint8_t buttons) {
    int sw = get_screen_width();
    int sh = get_screen_height();
    
    prev_mx = mx;
    prev_my = my;
    
    mouse_accum_x += dx * mouse_speed;
    mouse_accum_y += dy * mouse_speed;
    
    int move_x = mouse_accum_x / 10;
    int move_y = mouse_accum_y / 10;
    
    mouse_accum_x -= move_x * 10;
    mouse_accum_y -= move_y * 10;
    
    mx += move_x;
    my += move_y;
    
    if (mx < 0) mx = 0;
    if (my < 0) my = 0;
    if (mx >= sw) mx = sw - 1;
    if (my >= sh) my = sh - 1;
    
    static bool prev_left = false;
    static bool prev_right = false;
    bool left = buttons & 0x01;
    bool right = buttons & 0x02;

    if (left && !prev_left) {
        drag_start_x = mx;
        drag_start_y = my;
        int dock_h = 60;
        int dock_y = sh - dock_h - 6;  
        int dock_item_size = 48;
        int dock_spacing = 10;
        int total_dock_width = 8 * (dock_item_size + dock_spacing);
        int dock_bg_x = (sw - total_dock_width) / 2 - 12;
        int dock_bg_w = total_dock_width + 24;
        
        if (rect_contains(dock_bg_x, dock_y, dock_bg_w, dock_h, mx, my)) {
            int dock_x = (sw - total_dock_width) / 2;
            
            // Check which dock item was clicked
            int item_x = mx - dock_x;
            if (item_x >= 0) {
                int item = item_x / (dock_item_size + dock_spacing);
                if (item == 0) start_menu_pending_app = "Files";
                else if (item == 1) start_menu_pending_app = "Settings";
                else if (item == 2) start_menu_pending_app = "Notepad";
                else if (item == 3) start_menu_pending_app = "Calculator";
                else if (item == 4) start_menu_pending_app = "Terminal";
                else if (item == 5) start_menu_pending_app = "Minesweeper";
                else if (item == 6) start_menu_pending_app = "Paint";
                else if (item == 7) start_menu_pending_app = "Clock";
            }
        } else {
            wm_handle_click(mx, my);
        }
    } else if (right && !prev_right) {
        wm_handle_right_click(mx, my);
    } else if (left && is_dragging && drag_window) {
        drag_window->x = mx - drag_offset_x;
        drag_window->y = my - drag_offset_y;
        // Mark for full redraw since window moved
        force_redraw = true;
    } else if (left && !is_dragging && !is_dragging_file && (dx != 0 || dy != 0)) {
        // Check deadzone
        int dist_x = mx - drag_start_x;
        int dist_y = my - drag_start_y;
        if (dist_x < 0) dist_x = -dist_x;
        if (dist_y < 0) dist_y = -dist_y;
        
        if (dist_x >= 5 || dist_y >= 5) {
            // Check for Start Menu Drag
            if (start_menu_pending_app) {
                // Start dragging app from start menu
                is_dragging_file = true;
                drag_icon_type = 2;
                // Construct special path for app drag
                char *p = drag_file_path;
                const char *prefix = "::APP::";
                while(*prefix) *p++ = *prefix++;
                char *n = start_menu_pending_app;
                while(*n) *p++ = *n++;
                *p = 0;
                start_menu_pending_app = NULL;
            }
            
            if (pending_desktop_icon_click != -1) {
                int i = pending_desktop_icon_click;
                DesktopIcon *icon = &desktop_icons[i];
                is_dragging_file = true;
                drag_icon_type = icon->type;
                pending_desktop_icon_click = -1; 
                drag_icon_orig_x = icon->x;
                drag_icon_orig_y = icon->y;
                // Construct path
                char path[128] = "/Desktop/";
                int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                int k=0; while(path[k]) { drag_file_path[k] = path[k]; k++; } drag_file_path[k]=0;
            }
            // 2. Check Explorer Items
            if (!is_dragging_file) {
                bool is_dir;
                if (explorer_get_file_at(drag_start_x, drag_start_y, drag_file_path, &is_dir)) {
                    is_dragging_file = true;
                    drag_icon_type = is_dir ? 1 : 0;
                    drag_src_win = NULL;
                    
                    // Find which explorer window was clicked to clear its state
                    for (int w = 0; w < window_count; w++) {
                        Window *win = all_windows[w];
                        if (win->visible && rect_contains(win->x, win->y, win->w, win->h, drag_start_x, drag_start_y)) {
                            if (str_starts_with(win->title, "Files")) {
                                drag_src_win = win;
                                explorer_clear_click_state(win);
                            }
                        }
                    }
                }
            }
            
            if (is_dragging_file) force_redraw = true;
        }
        
    } else if (!left) {
        if (is_dragging) {
            is_dragging = false;
            drag_window = NULL;
            force_redraw = true;
        }
        
        // Handle Dock App Click (Mouse Up without Drag)
        if (start_menu_pending_app) {
            // Launch App
            if (str_starts_with(start_menu_pending_app, "Files")) {
                explorer_open_directory("/");
            } else if (str_starts_with(start_menu_pending_app, "Notepad")) {
                Window *existing = wm_find_window_by_title("Notepad");
                if (existing) {
                    wm_bring_to_front(existing);
                } else {
                    process_create_elf("/bin/notepad.elf", NULL);
                }
            } else if (str_starts_with(start_menu_pending_app, "Editor")) {
                Window *existing = wm_find_window_by_title("Txtedit");
                if (existing) wm_bring_to_front(existing);
                else process_create_elf("/bin/txtedit.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "Terminal")) {
                cmd_reset(); wm_bring_to_front(&win_cmd);
            } else if (str_starts_with(start_menu_pending_app, "Calculator")) {
                Window *existing = wm_find_window_by_title("Calculator");
                if (existing) {
                    wm_bring_to_front(existing);
                } else {
                    process_create_elf("/bin/calculator.elf", NULL);
                }
            } else if (str_starts_with(start_menu_pending_app, "Minesweeper")) {
                Window *existing = wm_find_window_by_title("Minesweeper");
                if (existing) wm_bring_to_front(existing);
                else process_create_elf("/bin/minesweeper.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "Settings")) {
                Window *existing = wm_find_window_by_title("Settings");
                if (existing) wm_bring_to_front(existing);
                else process_create_elf("/bin/settings.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "Paint")) {
                Window *existing = wm_find_window_by_title("Paint");
                if (existing) wm_bring_to_front(existing);
                else process_create_elf("/bin/paint.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "Clock")) {
                Window *existing = wm_find_window_by_title("Clock");
                if (existing) wm_bring_to_front(existing);
                else process_create_elf("/bin/clock.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "About")) {
                process_create_elf("/bin/about.elf", NULL);
            } else if (str_starts_with(start_menu_pending_app, "Shutdown")) {
                k_shutdown();
            } else if (str_starts_with(start_menu_pending_app, "Restart")) {
                k_reboot();
            }
            
            start_menu_pending_app = NULL;
            force_redraw = true;
        }
        
        // Handle Desktop Icon Click (Mouse Up)
        if (pending_desktop_icon_click != -1) {
            int i = pending_desktop_icon_click;
            if (i < desktop_icon_count) {
                DesktopIcon *icon = &desktop_icons[i];
                bool handled = false;
                if (icon->type == 2) { // App Shortcut
                    // Check name to launch app
                    if (str_ends_with(icon->name, "Notepad.shortcut")) {
                        process_create_elf("/bin/notepad.elf", NULL); handled = true;
                    } else if (str_ends_with(icon->name, "Calculator.shortcut")) {
                        process_create_elf("/bin/calculator.elf", NULL); handled = true;
                    } else if (str_ends_with(icon->name, "Minesweeper.shortcut")) {
                        process_create_elf("/bin/minesweeper.elf", NULL); handled = true;
                    } else if (str_ends_with(icon->name, "Settings.shortcut")) {
                        process_create_elf("/bin/settings.elf", NULL); handled = true;
                    } else if (str_ends_with(icon->name, "Terminal.shortcut")) {
                        wm_bring_to_front(&win_cmd); handled = true;
                    } else if (str_ends_with(icon->name, "About.shortcut")) {
                        process_create_elf("/bin/about.elf", NULL); handled = true;
                    } else if (str_ends_with(icon->name, "Files.shortcut")) {
                        explorer_open_directory("/"); handled = true;
                    } else if (str_ends_with(icon->name, "Recycle Bin.shortcut")) {
                        explorer_open_directory("/RecycleBin"); handled = true;
                    } else if (str_ends_with(icon->name, "Paint.shortcut")) {
                        process_create_elf("/bin/paint.elf", NULL); handled = true;
                    }
                    
                    if (!handled) {
                        // Generic Shortcut Handling
                        char path[128] = "/Desktop/";
                        int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                        
                        if (str_ends_with(icon->name, ".shortcut") && !str_starts_with(icon->name, "Recycle Bin")) {
                            FAT32_FileHandle *fh = fat32_open(path, "r");
                            if (fh) {
                                char buf[256];
                                int len = fat32_read(fh, buf, 255);
                                fat32_close(fh);
                                if (len > 0) {
                                    buf[len] = 0;
                                    if (fat32_is_directory(buf)) {
                                        explorer_open_directory(buf);
                                    } else {
                                        process_create_elf("/bin/txtedit.elf", buf);
                                    }
                                    pending_desktop_icon_click = -1;
                                    force_redraw = true;
                                    return;
                                }
                            }
                        }
                    }
                } else if (icon->type == 1) { // Folder
                    char path[128] = "/Desktop/";
                    int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                    explorer_open_directory(path);
                } else { // File
                    char path[128] = "/Desktop/";
                    int p=9; int n=0; while(icon->name[n]) path[p++] = icon->name[n++]; path[p]=0;
                    
                    if (str_ends_with(icon->name, ".elf")) {
                        process_create_elf(path, NULL);
                    } else if (str_ends_with(icon->name, ".pnt")) {
                        process_create_elf("/bin/paint.elf", path);
                    } else if (str_ends_with(icon->name, ".md")) {
                        process_create_elf("/bin/markdown.elf", path);
                    } else if (str_ends_with(icon->name, ".jpg") || str_ends_with(icon->name, ".JPG")) {
                        process_create_elf("/bin/viewer.elf", path);
                    } else {
                        process_create_elf("/bin/txtedit.elf", path);
                    }
                }
            }
            pending_desktop_icon_click = -1;
        }
        
        if (is_dragging_file) {
            // Drop logic
            
            Window *drop_win = NULL;
            int topmost_z = -1;
            for (int w = 0; w < window_count; w++) {
                Window *win = all_windows[w];
                if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
                    if (win->z_index > topmost_z && str_starts_with(win->title, "Files")) {
                        drop_win = win;
                        topmost_z = win->z_index;
                    }
                }
            }

            if (drop_win) {
                char target_path[256];
                bool is_dir;
                // Check if dropped on a folder inside this explorer
                if (explorer_get_file_at(mx, my, target_path, &is_dir) && is_dir) {
                    explorer_import_file_to(drop_win, drag_file_path, target_path);
                } else {
                    // Dropped in current dir of this explorer
                    explorer_import_file(drop_win, drag_file_path);
                }

                if (str_starts_with(drag_file_path, "/Desktop/")) {
                    refresh_desktop_icons();
                }
            } else {
                // Dropped on Desktop (or elsewhere)
                if (drag_file_path[0] == ':' && drag_file_path[1] == ':' && drag_file_path[2] == 'A') {
                    create_desktop_shortcut(drag_file_path + 7); 
                } else {
                    bool from_desktop = (drag_file_path[0]=='/' && drag_file_path[1]=='D' && drag_file_path[2]=='e');
                    bool dropped_on_target = false;
                    for (int i = 0; i < desktop_icon_count; i++) {
                        if (from_desktop) {
                            char path[128] = "/Desktop/";
                            int p=9; int n=0; while(desktop_icons[i].name[n]) path[p++] = desktop_icons[i].name[n++]; path[p]=0;
                            if (str_eq(path, drag_file_path) != 0) continue;
                        }

                        if (rect_contains(desktop_icons[i].x + 20, desktop_icons[i].y, 40, 40, mx, my)) {
                            if (desktop_icons[i].type == 1) {
                                char target_path[256] = "/Desktop/";
                                int p=9; int n=0; while(desktop_icons[i].name[n]) target_path[p++] = desktop_icons[i].name[n++]; target_path[p]=0;
                                explorer_import_file_to(&win_explorer, drag_file_path, target_path);
                                refresh_desktop_icons();
                                dropped_on_target = true;
                                break;
                            } else if (desktop_icons[i].type == 2 && str_starts_with(desktop_icons[i].name, "Recycle Bin")) {
                                explorer_import_file_to(&win_explorer, drag_file_path, "/RecycleBin");
                                refresh_desktop_icons();
                                dropped_on_target = true;
                                break;
                            } else {
                                dropped_on_target = true;
                                break;
                            }
                        }
                    }

                    if (!dropped_on_target && !from_desktop) {
                        // Dragged from Explorer to Desktop
                        // Check limit first
                        if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) {
                            wm_show_message("Error", "Desktop is full!");
                        } else {
                            explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop");
                        }
                        
                        // Handle insertion at specific position
                        char filename[64];
                        int len = 0; while(drag_file_path[len]) len++;
                        int s = len - 1; while(s >= 0 && drag_file_path[s] != '/') s--;
                        s++;
                        int d = 0; while(drag_file_path[s] && d < 63) filename[d++] = drag_file_path[s++];
                        filename[d] = 0;

                        if (desktop_auto_align && !msg_box_visible) {
                            int new_idx = -1;
                            for(int i=0; i<desktop_icon_count; i++) {
                                if (str_eq(desktop_icons[i].name, filename) != 0) {
                                    new_idx = i;
                                    break;
                                }
                            }
                            
                            if (new_idx != -1) {
                                int target_col = (mx - 20) / 80;
                                int target_row = (my - 20) / 80;
                                if (target_col < 0) target_col = 0;
                                if (target_row < 0) target_row = 0;
                                int target_idx = target_col * desktop_max_rows_per_col + target_row;
                                if (target_idx >= desktop_icon_count) target_idx = desktop_icon_count - 1;
                                
                                // Move new_idx to target_idx
                                DesktopIcon temp = desktop_icons[new_idx];
                                // Shift down to make space
                                for (int i = new_idx; i > target_idx; i--) desktop_icons[i] = desktop_icons[i-1];
                                desktop_icons[target_idx] = temp;
                                
                                refresh_desktop_icons(); // Re-apply layout
                            }
                        } else if (!desktop_auto_align && !msg_box_visible) {
                            for(int i=0; i<desktop_icon_count; i++) {
                                if (str_eq(desktop_icons[i].name, filename) != 0) {
                                    desktop_icons[i].x = mx - 20;
                                    desktop_icons[i].y = my - 20;
                                    if (desktop_snap_to_grid) {
                                        int col = (desktop_icons[i].x - 20 + 40) / 80;
                                        int row = (desktop_icons[i].y - 20 + 40) / 80;
                                        if (col < 0) col = 0; if (row < 0) row = 0;
                                        desktop_icons[i].x = 20 + col * 80;
                                        desktop_icons[i].y = 20 + row * 80;
                                    }
                                    break;
                                }
                            }
                        }
                    } else if (!dropped_on_target) {
                        int dragged_idx = -1;
                        for(int i=0; i<desktop_icon_count; i++) {
                            char path[128] = "/Desktop/";
                            int p=9; int n=0; while(desktop_icons[i].name[n]) path[p++] = desktop_icons[i].name[n++]; path[p]=0;
                            if (str_eq(path, drag_file_path) != 0) {
                                dragged_idx = i;
                                break;
                            }
                        }
                        
                        if (dragged_idx != -1) {
                            if (desktop_auto_align) {
                                int cell_h = 80;
                                int rel_y = my - 20;
                                if (rel_y < 0) rel_y = 0;
                                
                                int target_col = (mx - 20) / 80;
                                if (target_col < 0) target_col = 0;
                                
                                int target_row = rel_y / cell_h;
                                int row_offset = rel_y % cell_h;
                                
                                // 20% threshold logic: Only insert "before" if in the top 20%
                                if (row_offset > (int)(cell_h * 0.2)) {
                                    target_row++;
                                }
                                
                                int target_idx = target_col * desktop_max_rows_per_col + target_row;
                                if (target_idx >= desktop_icon_count) target_idx = desktop_icon_count - 1;
                                
                                // Shift items
                                DesktopIcon temp = desktop_icons[dragged_idx];
                                if (target_idx > dragged_idx) {
                                    for (int i = dragged_idx; i < target_idx; i++) desktop_icons[i] = desktop_icons[i+1];
                                } else {
                                    for (int i = dragged_idx; i > target_idx; i--) desktop_icons[i] = desktop_icons[i-1];
                                }
                                desktop_icons[target_idx] = temp;
                                refresh_desktop_icons(); // Re-applies layout
                            } else {
                                desktop_icons[dragged_idx].x = mx - 20;
                                desktop_icons[dragged_idx].y = my - 20;
                                if (desktop_snap_to_grid) {
                                    int col = (desktop_icons[dragged_idx].x - 20 + 40) / 80;
                                    int row = (desktop_icons[dragged_idx].y - 20 + 40) / 80;
                                    if (col < 0) col = 0;
                                    if (row < 0) row = 0;
                                    desktop_icons[dragged_idx].x = 20 + col * 80;
                                    desktop_icons[dragged_idx].y = 20 + row * 80;
                                }
                                
                                for (int i = 0; i < desktop_icon_count; i++) {
                                    if (i == dragged_idx) continue;
                                    int dx = desktop_icons[i].x - desktop_icons[dragged_idx].x;
                                    int dy = desktop_icons[i].y - desktop_icons[dragged_idx].y;
                                    if (dx < 0) dx = -dx;
                                    if (dy < 0) dy = -dy;
                                    if (dx < 35 && dy < 35) {
                                        // Revert position
                                        desktop_icons[dragged_idx].x = drag_icon_orig_x;
                                        desktop_icons[dragged_idx].y = drag_icon_orig_y;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            is_dragging_file = false;
            force_redraw = true;
        }
    }
    
    if (is_dragging_file) {
        force_redraw = true;
    }
    
    // Send mouse events to userland windows
    if (left && !prev_left) {
        // Left button pressed - send MOUSE_DOWN event to topmost window
        Window *topmost = NULL;
        int topmost_z = -1;
        for (int w = 0; w < window_count; w++) {
            Window *win = all_windows[w];
            if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
                if (win->z_index > topmost_z) {
                    topmost = win;
                    topmost_z = win->z_index;
                }
            }
        }
        if (topmost && topmost->data) {
            if (my >= topmost->y + 20)
                syscall_send_mouse_down_event(topmost, mx - topmost->x, my - topmost->y - 20);
        }
    }
    
    if (!left && prev_left) {
        // Left button released - send MOUSE_UP event to topmost window
        Window *topmost = NULL;
        int topmost_z = -1;
        for (int w = 0; w < window_count; w++) {
            Window *win = all_windows[w];
            if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
                if (win->z_index > topmost_z) {
                    topmost = win;
                    topmost_z = win->z_index;
                }
            }
        }
        if (topmost && topmost->data) {
            if (my >= topmost->y + 20)
                syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y - 20);
        }
    }
    
    if (dx != 0 || dy != 0) {
        // Mouse moved - send MOUSE_MOVE event to topmost window
        Window *topmost = NULL;
        int topmost_z = -1;
        for (int w = 0; w < window_count; w++) {
            Window *win = all_windows[w];
            if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
                if (win->z_index > topmost_z) {
                    topmost = win;
                    topmost_z = win->z_index;
                }
            }
        }
        if (topmost && topmost->data) {
            if (my >= topmost->y + 20)
                syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y - 20, buttons);
        }
    }
    
    prev_left = left;
    prev_right = right;
    
    if (prev_mx != mx || prev_my != my) {
        // Cursor moved - just mark dirty cursor areas
        wm_mark_dirty(prev_mx, prev_my, 10, 10);
        wm_mark_dirty(mx, my, 10, 10);
    }
    
    prev_left = left;
}

// Input Queue
#define INPUT_QUEUE_SIZE 128
static char key_queue[INPUT_QUEUE_SIZE];
static volatile int key_head = 0;
static volatile int key_tail = 0;

static void wm_dispatch_key(char c) {
    if (desktop_dialog_state != 0) {
        int len = 0; while(desktop_dialog_input[len]) len++;
        if (c == '\n') {
            if (desktop_dialog_state == 8) { // Rename
                char old_path[128] = "/Desktop/";
                char new_path[128] = "/Desktop/";
                int p=9; int n=0; while(desktop_icons[desktop_dialog_target].name[n]) old_path[p++] = desktop_icons[desktop_dialog_target].name[n++]; old_path[p]=0;
                p=9; n=0; while(desktop_dialog_input[n]) new_path[p++] = desktop_dialog_input[n++]; new_path[p]=0;
                if (fat32_rename(old_path, new_path)) {
                    refresh_desktop_icons();
                    explorer_refresh_all();
                }
            } else if (desktop_dialog_state == 1 || desktop_dialog_state == 2) { // Create File/Folder
                if (desktop_icon_count >= desktop_max_cols * desktop_max_rows_per_col) {
                    wm_show_message("Error", "Desktop is full!");
                } else if (desktop_dialog_input[0] != 0) {
                    char path[128] = "/Desktop/";
                    int p=9; int n=0; while(desktop_dialog_input[n]) path[p++] = desktop_dialog_input[n++]; path[p]=0;
                    if (desktop_dialog_state == 1) {
                        FAT32_FileHandle *fh = fat32_open(path, "w");
                        if (fh) fat32_close(fh);
                    } else {
                        fat32_mkdir(path);
                    }
                    refresh_desktop_icons();
                    explorer_refresh_all();
                }
            }
            desktop_dialog_state = 0;
        } else if (c == 27) {
            desktop_dialog_state = 0;
        } else if (c == '\b' || c == 127) {
            if (desktop_dialog_cursor > 0) {
                for(int i = desktop_dialog_cursor - 1; i < len; i++) desktop_dialog_input[i] = desktop_dialog_input[i+1];
                desktop_dialog_cursor--;
            }
        } else if (c == 19) { // Left
            if (desktop_dialog_cursor > 0) desktop_dialog_cursor--;
        } else if (c == 20) { // Right
            if (desktop_dialog_cursor < len) desktop_dialog_cursor++;
        } else if (c >= 32 && c <= 126 && len < 63) {
            for(int i = len; i >= desktop_dialog_cursor; i--) desktop_dialog_input[i+1] = desktop_dialog_input[i];
            desktop_dialog_input[desktop_dialog_cursor] = c;
            desktop_dialog_cursor++;
        }
        force_redraw = true;
        return;
    }

    Window *target = NULL;
    for (int i = 0; i < window_count; i++) {
        if (all_windows[i]->focused && all_windows[i]->visible) {
            target = all_windows[i];
            break;
        }
    }
    
    if (!target) return;
    
    if (target->handle_key) {
        target->handle_key(target, c);
    }
    
    // Mark window as needing redraw on next timer tick
    wm_mark_dirty(target->x, target->y, target->w, target->h);
}

void wm_handle_key(char c) {
    int next = (key_head + 1) % INPUT_QUEUE_SIZE;
    if (next != key_tail) {
        key_queue[key_head] = c;
        key_head = next;
    }
}

void wm_process_input(void) {
    if (periodic_refresh_pending) {
        if (!is_dragging && !is_dragging_file) {
            refresh_desktop_icons();
            explorer_refresh_all();
            force_redraw = true;
        }
        periodic_refresh_pending = false;
    }

    uint64_t rflags;
    asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
    while (key_head != key_tail) {
        char c = key_queue[key_tail];
        key_tail = (key_tail + 1) % INPUT_QUEUE_SIZE;
        wm_dispatch_key(c);
    }
    asm volatile("push %0; popfq" : : "r"(rflags));
}

void wm_mark_dirty(int x, int y, int w, int h) {
    graphics_mark_dirty(x, y, w, h);
}

void wm_refresh(void) {
    force_redraw = true;
}

void wm_process_deferred_thumbs(void) {
    if (thumb_queue_head == thumb_queue_tail) return;
    
    char path[256];
    int i = 0;
    while (thumb_request_queue[thumb_queue_head][i]) {
        path[i] = thumb_request_queue[thumb_queue_head][i];
        i++;
    }
    path[i] = 0;

    // Pop from queue
    thumb_queue_head = (thumb_queue_head + 1) % THUMB_QUEUE_SIZE;
    
    // Process (this takes time but it's okay because we are in the main loop with IRQs enabled)
    thumb_cache_decode(path);
    force_redraw = true;
}

void wm_init(void) {
    disk_manager_init();
    disk_manager_scan();
    // Drives are now dynamically managed - only real drives are registered

    cmd_init();
    explorer_init();
    wallpaper_init();
    
    refresh_desktop_icons();
    
    // Initialize z-indices
    win_cmd.z_index = 0;
    win_explorer.z_index = 1;
    
    all_windows[0] = &win_cmd;
    all_windows[1] = &win_explorer;
    window_count = 2;
    
    win_explorer.visible = false;
    win_explorer.focused = false;
    win_explorer.z_index = 10;
    
    win_cmd.visible = false;
    
    force_redraw = true;
}

uint32_t wm_get_ticks(void) {
    return timer_ticks;
}

// Called by timer interrupt ~60Hz
void wm_timer_tick(void) {
    timer_ticks++;
    
    if (!is_dragging && !is_dragging_file) {
        // Periodic refresh removed - now triggered by FS events
    }
    
    static uint8_t last_second = 0xFF;
    
    outb(0x70, 0x00);
    uint8_t current_sec = inb(0x71);
    
    if (current_sec != last_second) {
        last_second = current_sec;
        int sw = get_screen_width();
        wm_mark_dirty(sw - 110, 6, 110, 24);
    }
    
    if (force_redraw) {
        graphics_mark_screen_dirty();
        force_redraw = false;
    }
    
    DirtyRect dirty = graphics_get_dirty_rect();
    if (dirty.active) {
        wm_paint();
        graphics_clear_dirty();
    }
}

void wm_notify_fs_change(void) {
    periodic_refresh_pending = true;
}
