#!/usr/bin/env python
#
# This file is part of Cynthion.
#
# Copyright (c) 2023 Great Scott Gadgets <info@greatscottgadgets.com>
# SPDX-License-Identifier: BSD-3-Clause

""" Cynthion 'setup' command. """

import logging, os, shutil, subprocess, sys

from .util import find_cynthion_asset

MANAGED_UDEV_PATH   = "/usr/lib/udev/rules.d"
UNMANAGED_UDEV_PATH = "/etc/udev/rules.d"
UDEV_CYNTHION       = "54-cynthion.rules"


def cynthion_setup(args):
    if args.check:
        _check_udev(args)
    else:
        _uninstall_udev(args)


def _check_udev(args):
    logging.info("Checking: Linux udev rules")

    managed_sys_path = os.path.join(MANAGED_UDEV_PATH, UDEV_CYNTHION)
    unmanaged_sys_path = os.path.join(UNMANAGED_UDEV_PATH, UDEV_CYNTHION)

    if not os.path.isfile(managed_sys_path):
        logging.error(f"❌\t{UDEV_CYNTHION} not installed in {MANAGED_UDEV_PATH}")
        logging.info("\nPlease run `sudo pacman -S python-cynthion`.")
        sys.exit(1)

    logging.info(f"✅\t{UDEV_CYNTHION} is managed by Pacman")

    sys_rules     = open(managed_sys_path, "r").readlines()
    factory_rules = open(find_cynthion_asset(UDEV_CYNTHION), "r").readlines()

    if sys_rules != factory_rules:
        logging.error(f"❌\t{UDEV_CYNTHION} differs from factory rules")
        logging.info("\nPlease re-install the `python-cynthion` package.")
        sys.exit(1)

    logging.info(f"✅\t{UDEV_CYNTHION} matches factory rules")

    if os.path.isfile(unmanaged_sys_path):
        logging.error(f"❌\tFound an unmanaged copy of {UDEV_CYNTHION} under {UNMANAGED_UDEV_PATH}.")
        logging.info("\nPlease run 'cynthion setup' to remove.")
        sys.exit(1)
    
    logging.info(f"✅\tNo unmanaged shadow copy of {UDEV_CYNTHION} found")
    logging.info("\nAll checks completed successfully.")


def _uninstall_udev(args):
    logging.info("Uninstalling: unmanaged Linux udev rules file")

    unmanaged_rules = os.path.join(UNMANAGED_UDEV_PATH, UDEV_CYNTHION)

    if os.path.isfile(unmanaged_rules):
        # remove unmanaged udev rules file
        _run_shell_command(f"rm {unmanaged_rules}", root=True)

        # reload udev rules
        _run_shell_command("udevadm control --reload", root=True)

        # apply udev rules to any devices that are already plugged in
        _run_shell_command("udevadm trigger", root=True)
    else:
        logging.info(f"✅\t{unmanaged_rules} not present, skipping.")

    logging.info("\nUninstallation completed successfully.")


def _run_shell_command(cmd, root=False):

    if root and os.getuid() != 0:
        SUDO_PATH = shutil.which('sudo')
        if SUDO_PATH is None:
            raise OSError('Cannot find sudo executable.')
        cmd = f"sudo {cmd}"
        
    proc = subprocess.Popen(args=cmd.split())
    proc.wait()

    if proc.returncode != 0:
        logging.error(f"❌\t{cmd} failed with exit code: {proc.returncode}")
        sys.exit(proc.returncode)

    logging.info(f"✅\t{cmd}")
