import { bind, timeout } from 'astal';
import { App, Gtk, Widget } from 'astal/gtk3';

import AstalNotifd from 'gi://AstalNotifd';

import { Notification, HasNotifs } from './notification';
import NotifGestureWrapper from './gesture';


const addNotif = (box: Widget.Box, notifObj: AstalNotifd.Notification) => {
    if (notifObj) {
        const NewNotif = Notification({
            id: notifObj.id,
            slide_in_from: 'Right',
        });

        if (NewNotif) {
            box.pack_end(NewNotif, false, false, 0);
            box.show_all();
        }
    }
};

const NotificationList = () => {
    const notifications = AstalNotifd.get_default();

    return (
        <box
            vertical
            vexpand
            valign={Gtk.Align.START}
            visible={bind(HasNotifs)}
            // It needs to be bigger than the notifs to not jiggle
            css="min-width: 550px;"

            setup={(self) => {
                notifications.get_notifications().forEach((n) => {
                    addNotif(self, n);
                });

                self
                    .hook(notifications, 'notified', (_, id) => {
                        if (id) {
                            const notifObj = notifications.get_notification(id);

                            if (notifObj) {
                                addNotif(self, notifObj);
                            }
                        }
                    })
                    .hook(notifications, 'resolved', (_, id) => {
                        const notif = (self.get_children() as NotifGestureWrapper[])
                            .find((ch) => ch.id === id);

                        if (notif?.get_sensitive()) {
                            notif.slideAway('Right');
                        }
                    });
            }}
        />
    );
};

const ClearButton = () => {
    const notifications = AstalNotifd.get_default();

    return (
        <eventbox
            cursor={bind(HasNotifs).as((hasNotifs) => hasNotifs ? 'pointer' : 'not-allowed')}
        >
            <button
                className="clear"
                sensitive={bind(HasNotifs)}

                onButtonReleaseEvent={() => {
                    notifications.get_notifications().forEach((notif) => {
                        notif.dismiss();
                    });
                    timeout(1000, () => {
                        App.get_window('win-notif-center')?.set_visible(false);
                    });
                }}
            >
                <box>
                    <label label="Clear " />

                    <icon icon={bind(notifications, 'notifications')
                        .as((notifs) => notifs.length > 0 ?
                            'user-trash-full-symbolic' :
                            'user-trash-symbolic')}
                    />
                </box>
            </button>
        </eventbox>
    );
};

const Header = () => (
    <box className="header">
        <label
            label="Notifications"
            hexpand
            xalign={0}
        />
        <ClearButton />
    </box>
);

const Placeholder = () => (
    <revealer
        transitionType={Gtk.RevealerTransitionType.CROSSFADE}
        revealChild={bind(HasNotifs).as((v) => !v)}
    >
        <box
            className="placeholder"
            vertical
            valign={Gtk.Align.CENTER}
            halign={Gtk.Align.CENTER}
            vexpand
            hexpand
        >
            <icon icon="notification-disabled-symbolic" />
            <label label="Your inbox is empty" />
        </box>
    </revealer>
);

export default () => (
    <box
        className="notification-center widget"
        vertical
    >
        <Header />

        <box className="notification-wallpaper-box">
            <scrollable
                className="notification-list-box"
                hscroll={Gtk.PolicyType.NEVER}
                vscroll={Gtk.PolicyType.AUTOMATIC}
            >
                <box
                    className="notification-list"
                    vertical
                >
                    <NotificationList />

                    <Placeholder />
                </box>
            </scrollable>
        </box>
    </box>
);