import AstalTray from "gi://AstalTray";
import { bind, GObject } from "astal";
import AstalHyprland from "gi://AstalHyprland";
import { Gtk } from "astal/gtk4";
import Pango from "gi://Pango?version=1.0";

const hypr = AstalHyprland.get_default();
const SYNC = GObject.BindingFlags.SYNC_CREATE;

const SysTray = () => {
    const trayBox = new Gtk.Box({ cssClasses: ["bar-button"] });
    const tray = AstalTray.get_default();

    const trayItems = new Map<string, Gtk.MenuButton>();
    const trayAddedHandler = tray.connect("item-added", (_, id) => {
        const item = tray.get_item(id);
        const popover = Gtk.PopoverMenu.new_from_model(item.menu_model);
        const icon = new Gtk.Image();
        const button = new Gtk.MenuButton({
            popover,
            child: icon,
            cssClasses: ["tray-item"],
        });

        item.bind_property("gicon", icon, "gicon", SYNC);
        popover.insert_action_group("dbusmenu", item.action_group);
        item.connect("notify::action-group", () => {
            popover.insert_action_group("dbusmenu", item.action_group);
        });

        trayItems.set(id, button);
        trayBox.append(button);
    });

    const trayRemovedHandler = tray.connect("item-removed", (_, id) => {
        const button = trayItems.get(id);
        if (button) {
            trayBox.remove(button);
            button.run_dispose();
            trayItems.delete(id);
        }
    });

    trayBox.connect("destroy", () => {
        tray.disconnect(trayAddedHandler);
        tray.disconnect(trayRemovedHandler);
    });

    return trayBox;
};

const Workspace = () => {
    return (
        <box>
            {bind(hypr, "workspaces").as(wss =>
                wss
                    .filter(ws => !(ws.id >= -99 && ws.id <= -2)) // filter out special workspaces
                    .sort((a, b) => a.id - b.id)
                    .map(ws => (
                        <button
                            cssClasses={bind(hypr, "focusedWorkspace").as(fw =>
                                ws === fw
                                    ? [
                                        "focused-workspace-button",
                                        "workspace-button",
                                    ]
                                    : ["workspace-button"],
                            )}
                            onButtonPressed={() => ws.focus()}
                            child={<label label={String(ws.id)}></label>}
                        ></button>
                    )),
            )}
        </box>
    );
};

/**
 * Displays the name of the currently active window and provides a popover for
 * displaying all available clients
 */
const ActiveWindow = () => {
    const focused = bind(hypr, "focusedClient");

    const WindowPopover = (): Gtk.Popover => {
        // Set up boxes + Popover
        const popover = new Gtk.Popover();

        const popoverBox = WindowPopoverBox();

        popover.set_child(popoverBox);
        return popover;
    };

    const windowPopover = WindowPopover();

    // ───────────────────────────────────────────────────────────────────
    // Return fully assembled HyprlandFocusedClient box
    // ───────────────────────────────────────────────────────────────────
    return (
        <box visible={focused.as(Boolean)}>
            <button
                onClicked={() => windowPopover.popup()}
                cssClasses={["bar-button"]}
                child={
                    focused.as(
                        client =>
                            client && (
                                <label
                                    maxWidthChars={70}
                                    ellipsize={Pango.EllipsizeMode.END}
                                    label={bind(client, "title").as(String)} />
                            ),
                    )
                }></button>
            {windowPopover}
        </box >
    );
};

const WindowPopoverBox = () => {
    return <box vertical>
        <label label={"Available Windows"} cssClasses={['title-2']}></label>
        <Gtk.Separator marginTop={5} marginBottom={5}></Gtk.Separator>
        <box vertical>
            {bind(hypr, 'clients').as(clients => {
                return clients.map(client => {
                    return <button child={
                        <box>
                            <label label={bind(client, 'workspace').as(w => `(WS ${w.name})`)}></label>
                            <label label={bind(client, 'initialClass').as(c => `[${c}]`)}></label>
                            <label label={bind(client, 'title')}></label>
                        </box>
                    }
                        onClicked={() => client.focus()}
                    ></button>
                })
            })}
        </box>
    </box>
}

export default {
    Workspace,
    ActiveWindow,
    SysTray,
};
