import { Variable, bind } from "astal";
import { App, Astal, Gtk } from "astal/gtk4";
import { hideWindow } from "@lib/utils";

import Hyprland from "gi://AstalHyprland";
import Apps from "gi://AstalApps";

const hide = () => App.get_window("launcher")?.hide();

function AppButton({ app }: { app: Apps.Application }) {
    return <button
        cssClasses={["application"]}
        onClicked={() => {
            hide();
        	app.launch();
		}}
    >
        <box>
            <image iconName={app.iconName} />
            <box valign={Gtk.Align.CENTER} vertical>
                <label
                    cssClasses={["name"]}
                    xalign={0}
                    label={app.name}
                />
                {app.description && <label
                    cssClasses={["description"]}
                    wrap
                    xalign={0}
                    label={app.description}
                />}
            </box>
        </box>
    </button>
}

export default function Launcher(_monitor_id: number) {
    const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor;

	const hypr = Hyprland.get_default();
    const apps = new Apps.Apps();

    const query = Variable("")
    const list = query(text => apps.fuzzy_query(text).slice(0, 10))
    const onEnter = () => {
        hide()
        list.get().at(0)!.launch()
    }

    return <window
        visible={false}
        monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
        name={"launcher"}
        cssClasses={["launcher"]}
        keymode={Astal.Keymode.EXCLUSIVE}
        anchor={TOP | BOTTOM | LEFT | RIGHT}
        onKeyPressed={hideWindow}
        application={App}>
        <box hexpand={false} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
            <box cssClasses={["launcher"]} vertical>
                <entry
                    placeholderText="Search"
                    onChanged={self => query.set(self.text)}
                    onActivate={onEnter}
                />
                <box spacing={6} vertical>
                    {list.as(list => list.map(app => (
                        <AppButton app={app} />
                    )))}
                </box>
                <box
                    halign={Gtk.Align.CENTER}
                    cssClasses={["not-found"]}
                    vertical
                    visible={list.as(l => l.length === 0)}>
                    <image iconName="system-search-symbolic" />
                    <label label="No match found" />
                </box>
            </box>
        </box>
    </window>
}
