#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# === This file is part of Calamares - <https://calamares.io> ===
#
#   SPDX-FileCopyrightText: 2025 Anke Boersma <demm@kaosx.us>
#   SPDX-License-Identifier: GPL-3.0-or-later
#
#   Calamares is Free Software: see the License-Identifier above.
#

import libcalamares

import os
import subprocess

from libcalamares.utils import check_target_env_call

import gettext
_ = gettext.translation("calamares-python",
                        localedir=libcalamares.utils.gettext_path(),
                        languages=libcalamares.utils.gettext_languages(),
                        fallback=True).gettext


def pretty_name():
    return _("Install Limine Bootloader.")

def get_uuid():
    root_mount_point = libcalamares.globalstorage.value("rootMountPoint")
    print(root_mount_point)
    partitions = libcalamares.globalstorage.value("partitions")
    print(partitions)
    for partition in partitions:
        if partition["mountPoint"] == "/":
            libcalamares.utils.debug(partition["uuid"])
            return partition["uuid"]
    return ""

def get_zfs_root():
    """
    Looks in global storage to find the zfs root

    :return: A string containing the path to the zfs root or None if it is not found
    """

    zfs = libcalamares.globalstorage.value("zfsDatasets")

    if not zfs:
        libcalamares.utils.warning("Failed to locate zfs dataset list")
        return None

    # Find the root dataset
    for dataset in zfs:
        try:
            if dataset["mountpoint"] == "/":
                return dataset["zpool"] + "/" + dataset["dsName"]
        except KeyError:
            # This should be impossible
            libcalamares.utils.warning("Internal error handling zfs dataset")
            raise

    return None

def is_zfs_root(partition):
    """ Returns True if the partition object refers to a zfs root filesystem

    :param partition: A partition map from global storage
    :return: True if zfs and root, False otherwise
    """
    return partition["mountPoint"] == "/" and partition["fs"] == "zfs"


def create_conf(uuid, conf_path):
    #timeout = libcalamares.job.configuration["timeout"]
    #distribution = libcalamares.job.configuration["distribution"]
    #protocol = libcalamares.job.configuration["protocol"]
    #module_path = libcalamares.job.configuration["module_path"]
    #fallback = libcalamares.job.configuration["fallback"]
    partitions = libcalamares.globalstorage.value("partitions")

    kernel_cmdline = ["quiet systemd.show_status=0"]
    swap = ""
    swap_luks = ""
    cryptdevice_params = []
    btrfs_params = ""
    zfs_params = ""

    for partition in partitions:
        if partition["fs"] == "linuxswap" and not "luksMapperName" in partition:
            swap = partition["uuid"]

        if partition["fs"] == "linuxswap" and "luksMapperName" in partition:
            swap_luks = partition["luksMapperName"]

        if partition["mountPoint"] == "/" and "luksMapperName" in partition:
            cryptdevice_params = [
                "cryptdevice=UUID={!s}:{!s}".format(partition["luksUuid"],
                                                    partition["luksMapperName"]),
                "root=/dev/mapper/{!s}".format(partition["luksMapperName"]),
                "resume=/dev/mapper/{!s}".format(partition["luksMapperName"])
            ]

        # Limine with a BTRFS root filesystem needs to be told
        # about the root subvolume.
        if partition["mountPoint"] == "/" and partition["fs"] == "btrfs":
            btrfs_params = "rootflags=subvol=@"

        # zfs needs to be told the location of the root dataset
        if is_zfs_root(partition):
            zfs_root_path = get_zfs_root()
            if zfs_root_path is not None:
                zfs_params = ("root=ZFS=" + zfs_root_path)
            else:
                # Something is really broken if we get to this point
                libcalamares.utils.warning("Internal error handling zfs dataset")
                raise Exception("Internal zfs data missing, please contact your distribution")

    if cryptdevice_params:
        kernel_cmdline.extend(cryptdevice_params)
    else:
        if zfs_params:
            kernel_cmdline.append(zfs_params)
        else:
            kernel_cmdline.append("root=UUID={!s}".format(uuid))

    if swap:
        kernel_cmdline.append("resume=UUID={!s}".format(swap))
    if swap_luks:
        kernel_cmdline.append("resume=/dev/mapper/{!s}".format(swap_luks))
    if btrfs_params:
        print('BTRFS')
        kernel_cmdline.append(btrfs_params)

    lines = [
        'timeout 10\n',
        'default_entry: 1\n',
        'interface_branding_colour: 1\n',
        'remember_last_entry: yes\n',
        'term_background: CC000000\n',
        'term_foreground: FFFFFF\n',
        'term_margin: 100\n',
        'wallpaper: boot():/limine/wallpaper.jpg\n\n',
        '/KaOS 2026.03\n',
        '    comment: KaOS GNU/Linux, with Linux kernel\n',
        '    protocol: linux\n',
        '    kernel_path: boot():/vmlinuz-linux\n',
        '    module_path: boot():/initramfs-linux.img\n',
        '    kernel_cmdline: {!s} rw\n\n'.format(" ".join(kernel_cmdline)),
        '',
        '/KaOS 2026.03 Fallback\n',
        '    comment: KaOS GNU/Linux, with Linux kernel, fallback\n',
        '    protocol: linux\n'
        '    kernel_path: boot():/vmlinuz-linux\n',
        '    module_path: boot():/initramfs-linux-fallback.img\n',
        '    kernel_cmdline: {!s} rw\n'.format(" ".join(kernel_cmdline)),
    ]

    with open(conf_path, 'w') as f:
        for l in lines:
            f.write(l)
    f.close()


def install_limine():
    install_path = libcalamares.globalstorage.value("rootMountPoint")
    uuid = get_uuid()
    conf_path = os.path.join(
        install_path, "boot", "limine", "limine.conf")
    partitions = libcalamares.globalstorage.value("partitions")
    device = ""

    for partition in partitions:
        if partition["mountPoint"] == "/boot":
            libcalamares.utils.debug(partition["device"])
            boot_device = partition["device"]
            boot_p = boot_device[-1:]
            device = boot_device[:-1]
            if boot_device.startswith('/dev/nvme'):
                device = boot_device[:-2]

            if not boot_p or not device:
                return ("EFI directory /boot not found!",
                        "Boot partition: \"{!s}\"",
                        "Boot device: \"{!s}\"".format(boot_p, device))
            else:
                print("EFI directory: /boot")
                print("Boot partition: \"{!s}\"".format(boot_p))
                print("Boot device: \"{!s}\"".format(device))

    if not device:
        print("WARNING: no EFI system partition or EFI system partition mount point not set.")
        print("         >>> no EFI bootloader will be installed <<<")
        return None
    print("Set 'EF00' flag")
    subprocess.call(
        ["sgdisk", "--typecode={!s}:EF00".format(boot_p), "{!s}".format(device)])
    cmd = [
        "efibootmgr",
        "--create",
        "--disk", f"{device}",
        "--part", f"{boot_p}",
        "--label", "KaOS with Limine Bootloader",
        "--loader", "/limine/BOOTX64.EFI"
    ]
    subprocess.call(cmd)
    create_conf(uuid, conf_path)


def run():
    #boot_loader = libcalamares.globalstorage.value("bootLoader")
    # Packagechooser@bootchoice outcome
    bootchoice = libcalamares.globalstorage.value("packagechooser_bootchoice")

    if bootchoice != 'limine':
        return None

    install_limine()
    return None
