import { bind, idle } from 'astal';
import { Gtk, Widget } from 'astal/gtk3';
import { register } from 'astal/gobject';

import AstalBluetooth from 'gi://AstalBluetooth';

import Separator from '../misc/separator';

/* Types */
interface DevToggleProps {
    label: string
    prop: keyof AstalBluetooth.Device
    onToggle: (active: boolean) => void
}


@register()
export default class DeviceWidget extends Widget.Revealer {
    readonly dev: AstalBluetooth.Device;

    constructor({ dev }: { dev: AstalBluetooth.Device }) {
        const bluetooth = AstalBluetooth.get_default();

        const DevToggle = ({ label, prop, onToggle }: DevToggleProps) => (
            <centerbox>
                <label
                    label={label}
                    valign={Gtk.Align.CENTER}
                    halign={Gtk.Align.START}
                />

                <box />

                <switch
                    cursor="pointer"
                    valign={Gtk.Align.CENTER}
                    halign={Gtk.Align.END}

                    active={bind(dev, prop).as(Boolean)}

                    setup={(self) => {
                        self.connect('notify::active', () => {
                            onToggle(self.active);
                        });
                    }}
                />
            </centerbox>
        );

        const rev = (
            <revealer
                transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}
            >
                <box vertical halign={Gtk.Align.FILL} hexpand>
                    <Separator size={8} vertical />

                    <DevToggle
                        label="Connected"
                        prop="connected"
                        onToggle={(active) => {
                            if (active) {
                                dev.connect_device();
                            }
                            else {
                                dev.disconnect_device();
                            }
                        }}
                    />

                    <Separator size={8} vertical />

                    <DevToggle
                        label="Trusted"
                        prop="trusted"
                        onToggle={(active) => {
                            dev.set_trusted(active);
                        }}
                    />

                    <Separator size={8} vertical />

                    <DevToggle
                        label="Paired"
                        prop="paired"
                        onToggle={(active) => {
                            if (active) {
                                dev.pair();
                            }
                            else {
                                bluetooth.get_adapter()?.remove_device(dev);
                            }
                        }}
                    />

                    <Separator size={8} vertical />

                    <DevToggle
                        label="Blocked"
                        prop="blocked"
                        onToggle={(active) => {
                            dev.set_blocked(active);
                        }}
                    />

                    <Separator size={8} vertical />
                </box>
            </revealer>
        ) as Widget.Revealer;

        const button = (
            <button
                cursor="pointer"
                onButtonReleaseEvent={() => {
                    rev.set_reveal_child(!rev.get_reveal_child());
                }}
            >
                <box>
                    <icon
                        icon={bind(dev, 'connected').as((isConnected) => isConnected ?
                            'check-active-symbolic' :
                            'check-mixed-symbolic')}

                        css={bind(dev, 'paired').as((isPaired) => isPaired ?
                            '' :
                            'opacity: 0;')}
                    />

                    <Separator size={8} />

                    <icon
                        icon={bind(dev, 'icon').as((iconName) =>
                            iconName ? `${iconName}-symbolic` : 'help-browser-symbolic')}
                    />

                    <Separator size={8} />

                    <label label={bind(dev, 'name')} />
                </box>
            </button>
        );

        super({
            revealChild: false,
            transitionType: Gtk.RevealerTransitionType.SLIDE_DOWN,

            child: (
                <box vertical>
                    {button}
                    {rev}
                    <Separator size={8} vertical />
                </box>
            ),
        });

        this.dev = dev;

        this.connect('realize', () => idle(() => {
            this.set_reveal_child(true);
        }));
    };
};