import app from "ags/gtk4/app";
import { Astal, Gtk } from "ags/gtk4";
import AstalNotifd from "gi://AstalNotifd";
import Notification from "./Notification";
import { createBinding, For, createState, onCleanup } from "ags";

export default function NotificationPopups() {
    const monitors = createBinding(app, "monitors");

    const notifd = AstalNotifd.get_default();

    const [notifications, setNotifications] = createState(
        new Array<AstalNotifd.Notification>(),
    );

    const notifiedHandler = notifd.connect("notified", (_, id, replaced) => {
        try {
            const notification = notifd.get_notification(id);
            if (!notification) {
                console.error(`Failed to get notification with id: ${id}`);
                return;
            }

            if (replaced && notifications.get().some((n) => n.id === id)) {
                setNotifications((ns) =>
                    ns.map((n) => (n.id === id ? notification : n)),
                );
            } else {
                setNotifications((ns) => [notification, ...ns]);
            }
        } catch (error) {
            console.error("Failed to handle notification:", error);
        }
    });

    const resolvedHandler = notifd.connect("resolved", (_, id) => {
        try {
            setNotifications((ns) => ns.filter((n) => n.id !== id));
        } catch (error) {
            console.error("Failed to resolve notification:", error);
        }
    });

    // technically, we don't need to cleanup because in this example this is a root component
    // and this cleanup function is only called when the program exits, but exiting will cleanup either way
    // but it's here to remind you that you should not forget to cleanup signal connections
    onCleanup(() => {
        notifd.disconnect(notifiedHandler);
        notifd.disconnect(resolvedHandler);
    });

    return (
        <For each={monitors} cleanup={(win) => (win as Gtk.Window).destroy()}>
            {(monitor) => (
                <window
                    class="NotificationPopups"
                    gdkmonitor={monitor}
                    visible={notifications((ns) => ns.length > 0)}
                    anchor={Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT}
                >
                    <box orientation={Gtk.Orientation.VERTICAL}>
                        <For each={notifications}>
                            {(notification) => (
                                <Notification
                                    notification={notification}
                                    onHoverLost={() =>
                                        setNotifications((ns) =>
                                            ns.filter((n) => n.id !== notification.id),
                                        )
                                    }
                                />
                            )}
                        </For>
                    </box>
                </window>
            )}
        </For>
    );
}
