#!/usr/bin/env python3
"""Write dev-embedded/remarkable-os-<device>-bin ebuilds from codexctl's version list.

Usage: os-image-ebuilds.py [--min X.Y] [--force] [version-ids.json]

The version list is codexctl's data/version-ids.json, fetched from GitHub
when no file is given. For each device, one ebuild is written per release at
or above --min (default 3.0) that has no ebuild yet; --force rewrites
existing ones too. Run "ebuild <file> manifest" in each package afterwards,
which downloads the images.
"""
import argparse
import json
import sys
import urllib.request
from pathlib import Path

VERSION_IDS = "https://raw.githubusercontent.com/Jayy001/codexctl/main/data/version-ids.json"
BASE_URI = "https://remarkable-software.s3.us-east-2.amazonaws.com"
CATEGORY = Path(__file__).resolve().parent.parent / "dev-embedded"
# version-ids.json key -> (device codename, as in remarkable-sdk-bin; model)
DEVICES = {
    "remarkable1": ("rm1", "reMarkable 1"),
    "remarkable2": ("rm2", "reMarkable 2"),
    "remarkablepp": ("ferrari", "reMarkable Paper Pro"),
    "remarkableppm": ("chiappa", "reMarkable Paper Pro Move"),
    "remarkableppure": ("tatsu", "reMarkable Paper Pure"),
}
# Releases up to here are protobuf .signed images, as in codexctl
LAST_SIGNED = (3, 11, 2, 5)
SIGNED_HW = {"rm1": "reMarkable", "rm2": "reMarkable2"}

TEMPLATE = """\
# Copyright 2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=8

# Generated by scripts/os-image-ebuilds.py from codexctl's version list.
# The update image reMarkable serves to the tablet: the complete root
# filesystem as a compressed ext4 image.  It is installed unchanged, to
# mount with rmufuse (dev-python/remarkable-update-fuse) or install on the
# tablet with codexctl (app-misc/codexctl).

DESCRIPTION="reMarkable OS update image for the {model}"
HOMEPAGE="https://remarkable.com/"
SRC_URI="{src_uri}"
S="${{WORKDIR}}"

# The image bundles GPL/LGPL parts alongside reMarkable's own software;
# reMarkable publishes no license terms for the whole
LICENSE="all-rights-reserved GPL-2 GPL-3 LGPL-2.1 LGPL-3 MIT BSD"
# One slot per X.Y release, so several releases can be compared side by side
SLOT="$(ver_cut 1-2)"
KEYWORDS="~amd64 ~arm64"
RESTRICT="bindist mirror"

src_unpack() {{
	# Installed as downloaded
	:
}}

src_install() {{
	insinto /usr/share/remarkable-os/${{PV}}
	doins "${{DISTDIR}}/${{A}}"
}}

pkg_postinst() {{
	elog "The image is in ${{EROOT}}/usr/share/remarkable-os/${{PV}}."
	elog "Mount it read-only with rmufuse (dev-python/remarkable-update-fuse):"
	elog "  rmufuse <image> <mountpoint>"
	elog "Install it on the tablet over SSH with codexctl (app-misc/codexctl),"
	elog "so the tablet doesn't download the update from reMarkable:"
	elog "  codexctl install <image>"
}}
"""

METADATA = """\
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
	<maintainer type="person">
		<email>claude@lermytte.be</email>
	</maintainer>
</pkgmetadata>
"""


def vkey(version):
    return tuple(int(n) for n in version.split("."))


def src_uri(dev, version, file_id):
    if vkey(version) <= LAST_SIGNED:
        return f"{BASE_URI}/omaha/{dev}/${{PV}}_{SIGNED_HW[dev]}-{file_id}.signed"
    return f"{BASE_URI}/{file_id.replace(version, '${PV}')}"


def main():
    ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
    ap.add_argument("--min", default="3.0", help="oldest X.Y release to write (default: 3.0)")
    ap.add_argument("--force", action="store_true", help="rewrite existing ebuilds")
    ap.add_argument("version_ids", nargs="?", help="path to version-ids.json")
    args = ap.parse_args()

    if args.version_ids:
        data = json.loads(Path(args.version_ids).read_text())
    else:
        with urllib.request.urlopen(VERSION_IDS, timeout=30) as resp:
            data = json.load(resp)

    written = 0
    for key, (dev, model) in DEVICES.items():
        pn = f"remarkable-os-{dev}-bin"
        pkg = CATEGORY / pn
        for version, (file_id, _sha256) in sorted(data.get(key, {}).items(),
                                                  key=lambda i: vkey(i[0])):
            if vkey(version)[:2] < vkey(args.min):
                continue
            ebuild = pkg / f"{pn}-{version}.ebuild"
            if ebuild.exists() and not args.force:
                continue
            pkg.mkdir(exist_ok=True)
            if not (pkg / "metadata.xml").exists():
                (pkg / "metadata.xml").write_text(METADATA)
            ebuild.write_text(TEMPLATE.format(
                model=model, src_uri=src_uri(dev, version, file_id)))
            written += 1
            print(ebuild.relative_to(CATEGORY.parent))
    print(f"{written} ebuild(s) written", file=sys.stderr)


if __name__ == "__main__":
    main()
