import os
import sys
import platform
import argparse

from . import cli
from . import udev
from . import devices
from . import get_first_mouse


_EPILOG = """
Please report any bug on Github: https://github.com/flozz/rivalcfg/issues
"""


def _check_linux():
    """Run some checks on Linux."""

    # Only run checks on Linux
    if platform.system() != "Linux":
        return

    # Skip check for root as there will be no issue for this user
    if os.getuid() == 0:
        return

    # Skip check if user is trying to update udev rules:
    if "--update-udev" in sys.argv:
        return

    if not os.path.isfile(udev.RULES_FILE_PATH):
        sys.stderr.write(
            "W: udev rules are not installed. You may not be able to open the device using a regular user.\n"
        )
        sys.stderr.write("   Run 'rivalcfg --update-udev' as root to fix.\n\n")
    elif not udev.is_rules_file_up_to_date():
        sys.stderr.write(
            "W: Installed udev rules were generated by an other rivalcfg version.\n"
        )
        sys.stderr.write("   Run 'rivalcfg --update-udev' as root to update.\n\n")


def _render_battery_level(level=None, is_charging=None):
    result = []

    if is_charging is not None:
        result.append("Charging" if is_charging else "Discharging")

    if level is not None:
        result.append("[%-10s] %i %%" % ("=" * int(level / 10), level))

    if is_charging is None and level is None:
        result.append("Unable to get the battery level")

    return " ".join(result)


def main(args=sys.argv[1:]):
    # Display a message when no argument given
    if len(sys.argv) == 1:
        print("USAGE:\n  rivalcfg --help")
        sys.exit(1)

    # On Linux: check udev rules
    _check_linux()

    # Try to open a mouse
    mouse = None
    if (
        "--print-debug" not in sys.argv
        and "--list" not in sys.argv
        and "--version" not in sys.argv
        and "--update-udev" not in sys.argv
        and "--print-udev" not in sys.argv
    ):
        try:
            mouse = get_first_mouse()
        except IOError as error:
            if "--help" not in sys.argv and "-h" not in sys.argv:
                raise error

    cli_parser = argparse.ArgumentParser(prog="rivalcfg", epilog=_EPILOG)
    cli.add_main_cli(cli_parser)

    if mouse:
        mouse_profile = devices.get_profile(
            vendor_id=mouse.vendor_id,
            product_id=mouse.product_id,
        )
        cli.add_mouse_cli(cli_parser, mouse_profile)

    settings = cli_parser.parse_args(args)

    # Print firmware and exit
    if hasattr(settings, "FIRMWARE_VERSION") and settings.FIRMWARE_VERSION:
        print("%s (firmware v%s)" % (mouse.name, mouse.firmware_version))
        sys.exit(0)

    # Print battery level and exit
    if hasattr(settings, "BATTERY_LEVEL") and settings.BATTERY_LEVEL:
        battery_info = mouse.battery
        print(
            _render_battery_level(
                battery_info["level"],
                battery_info["is_charging"],
            )
        )
        sys.exit(0)

    # Reset
    if mouse and settings.RESET:
        mouse.reset_settings()

    # Apply settings
    if mouse:
        for setting_name, value in [(k.lower(), v) for k, v in vars(settings).items()]:
            if value is None:
                continue
            method_name = "set_%s" % setting_name
            if not hasattr(mouse, method_name):
                continue
            getattr(mouse, method_name)(value)

        # Save settings in the internal device memory
        if settings.SAVE:
            mouse.save()


if __name__ == "__main__":
    main()
