#include "launch_screen.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>

/* ── colour helpers (duplicated locally to avoid coupling) ──────────────── */

static unsigned long lc_rgb(Display *dpy, int screen, int r, int g, int b)
{
    XColor c;
    c.red   = (unsigned short)(r << 8);
    c.green = (unsigned short)(g << 8);
    c.blue  = (unsigned short)(b << 8);
    c.flags = DoRed | DoGreen | DoBlue;
    if (!XAllocColor(dpy, DefaultColormap(dpy, screen), &c))
        return (r+g+b > 383) ? WhitePixel(dpy,screen) : BlackPixel(dpy,screen);
    return c.pixel;
}

/* ── rounded rect helpers ───────────────────────────────────────────────── */

static void ls_fill_rrect(Display *dpy, Drawable d, GC gc,
                           int x, int y, int w, int h, int r)
{
    if (r < 1) r = 1;
    if (2*r > w) r = w/2;
    if (2*r > h) r = h/2;
    XFillRectangle(dpy, d, gc, x+r,   y,   w-2*r, h);
    XFillRectangle(dpy, d, gc, x,     y+r, r,     h-2*r);
    XFillRectangle(dpy, d, gc, x+w-r, y+r, r,     h-2*r);
    XFillArc(dpy, d, gc, x,       y,       2*r, 2*r,  90*64,  90*64);
    XFillArc(dpy, d, gc, x+w-2*r, y,       2*r, 2*r,   0,     90*64);
    XFillArc(dpy, d, gc, x,       y+h-2*r, 2*r, 2*r, 180*64,  90*64);
    XFillArc(dpy, d, gc, x+w-2*r, y+h-2*r, 2*r, 2*r, 270*64,  90*64);
}

static void ls_draw_rrect(Display *dpy, Drawable d, GC gc,
                           int x, int y, int w, int h, int r)
{
    if (r < 1) r = 1;
    XDrawLine(dpy, d, gc, x+r,   y,     x+w-r-1, y);
    XDrawLine(dpy, d, gc, x+r,   y+h-1, x+w-r-1, y+h-1);
    XDrawLine(dpy, d, gc, x,     y+r,   x,       y+h-r-1);
    XDrawLine(dpy, d, gc, x+w-1, y+r,   x+w-1,   y+h-r-1);
    XDrawArc(dpy, d, gc, x,       y,       2*r, 2*r,  90*64,  90*64);
    XDrawArc(dpy, d, gc, x+w-2*r, y,       2*r, 2*r,   0,     90*64);
    XDrawArc(dpy, d, gc, x,       y+h-2*r, 2*r, 2*r, 180*64,  90*64);
    XDrawArc(dpy, d, gc, x+w-2*r, y+h-2*r, 2*r, 2*r, 270*64,  90*64);
}

/* ── init / free ────────────────────────────────────────────────────────── */

void launch_screen_init(LaunchState *ls, Display *dpy, Window win,
                         int screen, int sw, int sh, int footer_h)
{
    memset(ls, 0, sizeof(*ls));
    ls->dpy      = dpy;
    ls->win      = win;
    ls->screen   = screen;
    ls->sw       = sw;
    ls->sh       = sh;
    ls->footer_h = footer_h;

    ls->focused_btn = LAUNCH_BTN_START;  /* default: Start is highlighted   */

    /* fonts */
    ls->font_title = XLoadQueryFont(dpy,
        "-*-helvetica-bold-r-normal-*-28-*-*-*-*-*-*-*");
    if (!ls->font_title)
        ls->font_title = XLoadQueryFont(dpy, "fixed");

    ls->font_btn = XLoadQueryFont(dpy,
        "-*-helvetica-medium-r-normal-*-20-*-*-*-*-*-*-*");
    if (!ls->font_btn)
        ls->font_btn = XLoadQueryFont(dpy, "fixed");

    ls->font_sub = XLoadQueryFont(dpy,
        "-*-helvetica-medium-r-normal-*-13-*-*-*-*-*-*-*");
    if (!ls->font_sub)
        ls->font_sub = XLoadQueryFont(dpy, "fixed");

    /* GC */
    XGCValues gv;
    gv.foreground = BlackPixel(dpy, screen);
    gv.background = BlackPixel(dpy, screen);
    ls->gc = XCreateGC(dpy, win, GCForeground | GCBackground, &gv);

    /* back buffer */
    ls->backbuf = XCreatePixmap(dpy, win, sw, sh,
                                 DefaultDepth(dpy, screen));
}

void launch_screen_set_entry(LaunchState *ls, const DesktopEntry *entry)
{
    ls->entry       = entry;
    ls->focused_btn = LAUNCH_BTN_START;
    ls->glow_phase  = 0;
}

void launch_screen_tick(LaunchState *ls)
{
    ls->glow_phase = (ls->glow_phase + 6) & 0xFF;
}

int launch_screen_move(LaunchState *ls, int dir)
{
    LaunchButton next;
    if (dir < 0)
        next = (ls->focused_btn == LAUNCH_BTN_START)
               ? LAUNCH_BTN_BACK : LAUNCH_BTN_START;
    else
        next = (ls->focused_btn == LAUNCH_BTN_BACK)
               ? LAUNCH_BTN_START : LAUNCH_BTN_BACK;

    if (next == ls->focused_btn) return 0;
    ls->focused_btn = next;
    ls->glow_phase  = 0;
    return 1;
}

void launch_screen_free(LaunchState *ls)
{
    if (ls->font_title) XFreeFont(ls->dpy, ls->font_title);
    if (ls->font_btn)   XFreeFont(ls->dpy, ls->font_btn);
    if (ls->font_sub)   XFreeFont(ls->dpy, ls->font_sub);
    XFreeGC(ls->dpy, ls->gc);
    XFreePixmap(ls->dpy, ls->backbuf);
}

/* ── draw ───────────────────────────────────────────────────────────────── */

/*
 * Draw the Wii-style concave footer polygon (same curve as renderer.c).
 * Kept as a local copy so launch_screen.c has no dependency on renderer.c.
 */
static void ls_draw_footer(LaunchState *ls, Drawable d)
{
    Display *dpy  = ls->dpy;
    GC       gc   = ls->gc;
    int      w    = ls->sw;
    int      h    = ls->sh;
    int      fh   = ls->footer_h;
    int      ytop = h - fh;

    int side_flat = (int)(w * 0.12f);
    int dip_depth = (int)(fh * 0.28f);
    int curve_len = (int)(w * 0.20f);

    XPoint pts[300]; int n = 0;
    pts[n++] = (XPoint){0, (short)h};
    pts[n++] = (XPoint){0, (short)ytop};
    pts[n++] = (XPoint){(short)side_flat, (short)ytop};

    for (int i = 0; i <= 32; i++) {
        float t = i / 32.0f;
        float s = (1.0f - cosf(t * (float)M_PI)) * 0.5f;
        pts[n].x = (short)(side_flat + (int)(curve_len * t));
        pts[n].y = (short)(ytop + (int)(dip_depth * s));
        n++;
    }
    int cr = w - side_flat - curve_len;
    pts[n++] = (XPoint){(short)cr, (short)(ytop + dip_depth)};
    for (int i = 32; i >= 0; i--) {
        float t = i / 32.0f;
        float s = (1.0f - cosf(t * (float)M_PI)) * 0.5f;
        pts[n].x = (short)(w - side_flat - (int)(curve_len * t));
        pts[n].y = (short)(ytop + (int)(dip_depth * s));
        n++;
    }
    pts[n++] = (XPoint){(short)w, (short)ytop};
    pts[n++] = (XPoint){(short)w, (short)h};

    /* fill */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 206, 207, 215));
    XFillPolygon(dpy, d, gc, pts, n, Complex, CoordModeOrigin);

    /* thick cyan border (4 passes) */
    unsigned long border_col = lc_rgb(dpy, ls->screen, 127, 216, 246);
    for (int pass = 0; pass < 4; pass++) {
        XSetForeground(dpy, gc, border_col);
        XPoint bpts[300];
        for (int i = 1; i < n-2; i++) {
            bpts[i-1].x = pts[i].x;
            bpts[i-1].y = pts[i].y + (short)pass;
        }
        XDrawLines(dpy, d, gc, bpts, n-3, CoordModeOrigin);
    }
}

/*
 * Draw one pill-shaped button.
 *  focused  = 1 → cyan border + white face
 *  focused  = 0 → plain light-grey face
 */
static void ls_draw_pill(LaunchState *ls, Drawable d,
                          int x, int y, int w, int h,
                          const char *label, int focused)
{
    Display *dpy = ls->dpy;
    GC       gc  = ls->gc;
    int      r   = h / 2;   /* full-radius pill */

    /* shadow */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 150, 152, 162));
    ls_fill_rrect(dpy, d, gc, x+3, y+3, w, h, r);

    /* body */
    if (focused) {
        /* pulse the fill between white and very-light-cyan */
        double phase = ls->glow_phase / 255.0 * 2.0 * M_PI;
        double t = (sin(phase) + 1.0) / 2.0;
        int br = (int)(240 + t * 15);
        int bg2 = (int)(248 + t * 7);
        int bb  = 255;
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, br, bg2, bb));
    } else {
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 230, 232, 238));
    }
    ls_fill_rrect(dpy, d, gc, x, y, w, h, r);

    /* top gloss strip */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 255, 255, 255));
    ls_fill_rrect(dpy, d, gc, x+4, y+4, w-8, h/2-4, r-2);

    /* border */
    if (focused) {
        /* thick cyan ring (3 passes) */
        for (int pass = 0; pass < 3; pass++) {
            XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen,
                                            90-pass*10, 195, 235-pass*5));
            ls_draw_rrect(dpy, d, gc,
                          x-pass, y-pass, w+2*pass, h+2*pass, r+pass);
        }
    } else {
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 180, 183, 195));
        ls_draw_rrect(dpy, d, gc, x, y, w, h, r);
    }

    /* label */
    if (ls->font_btn && label && label[0]) {
        XSetFont(dpy, gc, ls->font_btn->fid);
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 60, 65, 80));
        int tw = XTextWidth(ls->font_btn, label, (int)strlen(label));
        int asc = ls->font_btn->ascent;
        XDrawString(dpy, d, gc,
                    x + w/2 - tw/2,
                    y + h/2 + asc/2 - 1,
                    label, (int)strlen(label));
    }
}

void launch_screen_draw(LaunchState *ls)
{
    Display *dpy = ls->dpy;
    Drawable  bb = ls->backbuf;
    GC        gc = ls->gc;
    int       w  = ls->sw;
    int       h  = ls->sh;
    int       fh = ls->footer_h;

    /* ── White background ── */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 255, 255, 255));
    XFillRectangle(dpy, bb, gc, 0, 0, w, h);

    /* ── Footer ── */
    ls_draw_footer(ls, bb);

    /* ── Green channel preview area ── */
    /* Matches the Wii's "banner" region: fills the upper content area
       with classic Wii channel green, with a rounded rectangle frame. */
    int preview_margin = 48;
    int preview_y      = preview_margin;
    int preview_h      = (h - fh) - preview_margin * 2;
    int preview_w      = w - preview_margin * 2;

    /* outer shadow */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 140, 143, 150));
    ls_fill_rrect(dpy, bb, gc,
                  preview_margin + 5, preview_y + 5,
                  preview_w, preview_h, 18);

    /* green fill */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 0, 220, 0));
    ls_fill_rrect(dpy, bb, gc,
                  preview_margin, preview_y,
                  preview_w, preview_h, 18);

    /* inner top gloss */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 80, 255, 80));
    ls_fill_rrect(dpy, bb, gc,
                  preview_margin + 6, preview_y + 6,
                  preview_w - 12, preview_h / 3, 14);

    /* border around preview */
    XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 0, 170, 0));
    ls_draw_rrect(dpy, bb, gc,
                  preview_margin, preview_y,
                  preview_w, preview_h, 18);

    /* App name centred in preview */
    if (ls->font_title && ls->entry) {
        const char *name = ls->entry->name;
        XSetFont(dpy, gc, ls->font_title->fid);
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 255, 255, 255));

        /* text shadow */
        int tw = XTextWidth(ls->font_title, name, (int)strlen(name));
        int tx = w/2 - tw/2;
        int ty = preview_y + preview_h/2 + ls->font_title->ascent/2;

        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 0, 100, 0));
        XDrawString(dpy, bb, gc, tx+2, ty+2, name, (int)strlen(name));

        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 255, 255, 255));
        XDrawString(dpy, bb, gc, tx, ty, name, (int)strlen(name));

        /* command line hint below name */
        if (ls->font_sub && ls->entry->exec[0]) {
            char hint[256];
            snprintf(hint, sizeof(hint), "Exec: %s", ls->entry->exec);
            XSetFont(dpy, gc, ls->font_sub->fid);
            XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 200, 255, 200));
            int hw2 = XTextWidth(ls->font_sub, hint, (int)strlen(hint));
            XDrawString(dpy, bb, gc,
                        w/2 - hw2/2, ty + ls->font_title->descent + 20,
                        hint, (int)strlen(hint));
        }
    }

    /* ── Pill buttons in footer ── */
    /*
     * Layout (matches screenshot):
     *   [  Wii Menu  ]     [▶  Start  ]
     * Both horizontally centred in the footer dip.
     */
    int btn_w  = (int)(w * 0.28f);
    int btn_h  = (int)(fh * 0.38f);
    if (btn_h < 48) btn_h = 48;
    int btn_gap = (int)(w * 0.06f);

    int dip_depth = (int)(fh * 0.28f);
    int footer_top = h - fh;
    int dip_y     = footer_top + dip_depth;
    int btn_area_h = h - dip_y;
    int btn_y      = dip_y + (btn_area_h - btn_h) / 2;

    int total_btn_w = btn_w * 2 + btn_gap;
    int btn_x_left  = w/2 - total_btn_w/2;
    int btn_x_right = btn_x_left + btn_w + btn_gap;

    ls_draw_pill(ls, bb,
                 btn_x_left, btn_y, btn_w, btn_h,
                 "Wii Menu",
                 ls->focused_btn == LAUNCH_BTN_BACK);

    /* Start button has a small play-triangle prefix */
    ls_draw_pill(ls, bb,
                 btn_x_right, btn_y, btn_w, btn_h,
                 "\x10 Start",          /* \x10 is ► in most fonts (DEC) */
                 ls->focused_btn == LAUNCH_BTN_START);

    /* navigation hint */
    if (ls->font_sub) {
        const char *hint = "← →: switch button   Enter: confirm   Esc: back";
        XSetFont(dpy, gc, ls->font_sub->fid);
        XSetForeground(dpy, gc, lc_rgb(dpy, ls->screen, 140, 143, 155));
        int hw3 = XTextWidth(ls->font_sub, hint, (int)strlen(hint));
        XDrawString(dpy, bb, gc,
                    w/2 - hw3/2, h - 8,
                    hint, (int)strlen(hint));
    }

    /* blit */
    XCopyArea(dpy, bb, ls->win, gc, 0, 0, w, h, 0, 0);
    XFlush(dpy);
}