# Borrowed from https://github.com/kotontrion/PKGBUILDS/blob/main/agsv1/PKGBUILD
#
# Maintainer: kotontrion <kotontrion@tutanota.de>

# This package is only intended to be used while migrating from ags v1.8.2 to ags v2.0.0.
# Many ags configs are quite big and it takes a while to migrate, therefore I made this package
# to install ags v1.8.2 as "agsv1", so both versions can be installed at the same time, making it
# possible to migrate bit by bit while still having a working v1 config around. 
#
# First update the aylurs-gtk-shell package to v2, then install this one.
#
# This package won't receive any updates anymore, so as soon as you migrated, uninstall this one.

pkgname=illogical-impulse-agsv1
_pkgname=ags
pkgver=1.9.0
pkgrel=1
pkgdesc="Aylurs's Gtk Shell (AGS), An eww inspired gtk widget system."
arch=('x86_64')
url="https://github.com/Aylur/ags"
license=('GPL-3.0-only')
makedepends=('git' 'gobject-introspection' 'meson' 'glib2-devel' 'npm' 'typescript')
depends=('gvfs' 'gjs' 'glib2' 'glib2-devel' 'glibc' 'gtk3' 'gtk-layer-shell' 'libpulse' 'pam' 'gnome-bluetooth-3.0' 'gammastep')
optdepends=('gnome-bluetooth-3.0: required for bluetooth service'
            'greetd: required for greetd service'
            'libdbusmenu-gtk3: required for systemtray service'
            'libsoup3: required for the Utils.fetch feature'
            'libnotify: required for sending notifications'
            'networkmanager: required for network service'
            'power-profiles-daemon: required for powerprofiles service'
            'upower: required for battery service')
conflicts=('illogical-impulse-ags')
backup=('etc/pam.d/ags')
source=("$pkgname-$pkgver.tar.gz::https://github.com/Aylur/ags/archive/refs/tags/v${pkgver}.tar.gz"
        "git+https://gitlab.gnome.org/GNOME/libgnome-volume-control")
sha256sums=('962f99dcf202eef30e978d1daedc7cdf213e07a3b52413c1fb7b54abc7bd08e6'
            SKIP)

prepare() {
  cd "$srcdir/$_pkgname-$pkgver"
  mv -T "$srcdir"/libgnome-volume-control subprojects/gvc

  # Overwrite greetd.ts with fixed version
  cat > src/service/greetd.ts << 'EOF'
import App from '../app.js';
import Service from '../service.js';
import GLib from 'gi://GLib';
import Gio from 'gi://Gio';

Gio._promisify(Gio.InputStream.prototype, 'read_bytes_async');
const SOCK = GLib.getenv('GREETD_SOCK');

type Request = {
    create_session: {
        username: string
    }
    post_auth_message_response: {
        response?: string
    }
    start_session: {
        cmd: string[]
        env: string[]
    }
    cancel_session: Record<never, never>
}

type Response = {
    type: 'success'
} | {
    type: 'error'
    error_type: 'auth_error' | 'error'
    description: string
} | {
    type: 'auth_message'
    auth_message_type: 'visible' | 'secret' | 'info' | 'error'
    auth_message: string
}

export class Greetd extends Service {
    static { Service.register(this); }

    private _decoder = new TextDecoder;

    readonly login = async (
        username: string,
        password: string,
        cmd: string[] | string,
        env: string[] = [],
    ) => {
        const session = await this.createSession(username);
        if (session.type !== 'auth_message') {
            this.cancelSession();
            throw session;
        }

        const auth = await this.postAuth(password);
        if (auth.type !== 'success') {
            this.cancelSession();
            throw auth;
        }

        const start = await this.startSession(cmd, env);
        if (start.type !== 'success') {
            this.cancelSession();
            throw start;
        }

        App.quit();
    };

    readonly createSession = (username: string) => {
        return this._send('create_session', { username });
    };

    readonly postAuth = (response?: string) => {
        return this._send('post_auth_message_response', { response });
    };

    readonly startSession = (cmd: string[] | string, env: string[] = []) => {
        const cmdv = Array.isArray(cmd)
            ? cmd
            : GLib.shell_parse_argv(cmd)[1];

        return this._send('start_session', { cmd: cmdv, env });
    };

    readonly cancelSession = () => {
        return this._send('cancel_session', {});
    };

    private async _send<R extends keyof Request>(req: R, payload: Request[R]): Promise<Response> {
    const connection = new Gio.SocketClient()
        .connect(new Gio.UnixSocketAddress({ path: SOCK }), null);

    try {
        const json = JSON.stringify({ type: req, ...payload });
        const ostream = new Gio.DataOutputStream({
            close_base_stream: true,
            base_stream: connection.get_output_stream(),
            byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN,
        });

        const istream = connection.get_input_stream();

        ostream.put_int32(json.length, null);
        ostream.put_string(json, null);

        const data = await istream.read_bytes_async(4, GLib.PRIORITY_DEFAULT, null);
        const raw = data.get_data();
        if (!raw) throw new Error("Failed to read length from greetd socket");
        const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
        const length = view.getUint32(0, true); // true = little endian

        const res = await istream.read_bytes_async(length, GLib.PRIORITY_DEFAULT, null);
        const resRaw = res.get_data();
        if (!resRaw) throw new Error("Failed to read response from greetd socket");

        return JSON.parse(this._decoder.decode(resRaw)) as Response;
    } finally {
        connection.close(null);
    }
}

}

export const greetd = new Greetd;
export default greetd;
EOF
}


build() {
  cd "$srcdir/$_pkgname-$pkgver"
  npm install
  arch-meson build --libdir "lib/$_pkgname" -Dbuild_types=true
  meson compile -C build
}

package() {
  cd "$srcdir/$_pkgname-$pkgver"
  meson install -C build --destdir "$pkgdir"
  rm ${pkgdir}/usr/bin/ags
  ln -sf /usr/share/com.github.Aylur.ags/com.github.Aylur.ags ${pkgdir}/usr/bin/agsv1
}
