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

import { SHELL } from "@/settings.json";

import Hyprland from "gi://AstalHyprland";

const hide = () => App.get_window("clipboard")?.hide();
type Entry = { id: string, content: string };

function ClipboardEntry({ id, content }: Entry) {
    return <button
        cssClasses={["entry"]}
        onClicked={() => {
            hide();
            execAsync([SHELL, "-c", `cliphist decode ${id} | wl-copy`]);
        }}
    >
        <box>
            <label
                cssClasses={["content"]}
                xalign={0}
                label={content}
            />
        </box>
    </button>
}

async function getClipboardHistory() {
    try {
        const ids = await execAsync([SHELL, "-c", "cliphist list | awk '{print $1}'"])
            .then(it => it.split("\n"));
        const contents = await execAsync([SHELL, "-c", "cliphist list | awk '{$1=\"\"; print}'"])
            .then(it => it.split("\n"));

        return ids
            .map((id, index) => ({ id, content: contents[index] }))
            .filter(({ content }) => content && content.length > 0);
    } catch {
        return [];
    }
}

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

    const history = await getClipboardHistory();
    const hypr = Hyprland.get_default();
    
    const toSkip = Variable(0);
    const list = bind(toSkip).as(count => limit(
        skip(history, count), 
        10
    ));

    const onScroll = (dy: number) => {
        const value = toSkip.get();
        
        if (dy < 0) {
            if ((value - 10) < 0) return;
            toSkip.set(value - 10)
        } else {
            if ((value + 10) > history.length) return;
            toSkip.set(value + 10)
        }
    };

    return <window
        visible={false}
        monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
        name={"clipboard"}
        cssClasses={["clipboard"]}
        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={["clipboard"]} vertical>
                <box spacing={6} vertical onScroll={(_, __, dy) => onScroll(dy)}>
                    {list.as(list => list.map(({ id, content }) => (
                        <ClipboardEntry id={id} content={content} />
                    )))}
                </box>
                <box
                    halign={Gtk.Align.CENTER}
                    cssClasses={["not-found"]}
                    vertical
                    visible={list.as(it => it.length === 0)}>
                    <image iconName="system-search-symbolic" />
                    <label label="No match found" />
                </box>
            </box>
        </box>
    </window>
}
