import logging
import os.path
from gettext import gettext as _

from lutris.config import LutrisConfig
from lutris.exceptions import MissingBiosError, MissingGameExecutableError
from lutris.runners.runner import Runner
from lutris.util import display, extract, system


def get_resolutions():
    try:
        screen_resolutions = [(resolution, resolution) for resolution in display.DISPLAY_MANAGER.get_resolutions()]
    except OSError:
        screen_resolutions = []
    screen_resolutions.insert(0, (_("Desktop resolution"), "desktop"))
    return screen_resolutions


class atari800(Runner):
    human_name = _("Atari800")
    # FIXME try to determine the actual computer used
    platform_dict = Runner.to_platform_dict([_("Atari 8bit computers")])
    runner_executable = "atari800/bin/atari800"
    bios_url = "https://netactuate.dl.sourceforge.net/project/atari800/ROM/Original%20XL%20ROM/xf25.zip?viasf=1"
    description = _("Atari 400, 800 and XL emulator")
    bios_checksums = {
        "xlxe_rom": "06daac977823773a3eea3422fd26a703",
        "basic_rom": "0bac0c6a50104045d902df4503a4c30b",
        "osa_rom": "",
        "osb_rom": "a3e8d617c95d08031fe1b20d541434b2",
        "5200_rom": "",
    }
    game_options = [
        {
            "option": "main_file",
            "type": "file",
            "label": _("ROM file"),
            "help": _(
                "The game data, commonly called a ROM image. \n"
                "Supported formats: ATR, XFD, DCM, ATR.GZ, XFD.GZ "
                "and PRO."
            ),
        }
    ]

    runner_options = [
        {
            "option": "bios_path",
            "type": "directory",
            "label": _("BIOS location"),
            "help": _(
                "A folder containing the Atari 800 BIOS files.\n"
                "They are provided by Lutris so you shouldn't have to "
                "change this."
            ),
        },
        {
            "option": "machine",
            "type": "choice",
            "choices": [
                (_("Emulate Atari 800"), "atari"),
                (_("Emulate Atari 800 XL"), "xl"),
                (_("Emulate Atari 320 XE (Compy Shop)"), "320xe"),
                (_("Emulate Atari 320 XE (Rambo)"), "rambo"),
                (_("Emulate Atari 5200"), "5200"),
            ],
            "default": "atari",
            "label": _("Machine"),
        },
        {
            "option": "fullscreen",
            "type": "bool",
            "default": False,
            "section": _("Graphics"),
            "label": _("Fullscreen"),
        },
        {
            "option": "resolution",
            "type": "choice",
            "choices": get_resolutions,
            "default": "desktop",
            "section": _("Graphics"),
            "label": _("Fullscreen resolution"),
        },
    ]

    def install(self, install_ui_delegate, version=None, callback=None):
        def on_runner_installed(*_args):
            config_path = system.create_folder("~/.atari800")
            bios_archive = os.path.join(config_path, "atari800-bioses.zip")
            install_ui_delegate.download_install_file(self.bios_url, bios_archive)
            if not system.path_exists(bios_archive):
                raise RuntimeError(_("Could not download Atari 800 BIOS archive"))
            extract.extract_archive(bios_archive, config_path)
            os.remove(bios_archive)
            config = LutrisConfig(runner_slug="atari800")
            config.raw_runner_config.update({"bios_path": config_path})
            config.save()
            if callback:
                callback()

        super().install(install_ui_delegate, version, on_runner_installed)

    def find_good_bioses(self, bios_path):
        """Check for correct bios files"""
        good_bios = {}
        for filename in os.listdir(bios_path):
            real_hash = system.get_md5_hash(os.path.join(bios_path, filename))
            for bios_file, checksum in self.bios_checksums.items():
                if real_hash == checksum:
                    logging.debug("%s Checksum : OK", filename)
                    good_bios[bios_file] = filename
        return good_bios

    def play(self):
        arguments = self.get_command()
        if self.runner_config.get("fullscreen"):
            arguments.append("-fullscreen")
        else:
            arguments.append("-windowed")

        resolution = self.runner_config.get("resolution")
        if resolution:
            if resolution == "desktop":
                width, height = display.DISPLAY_MANAGER.get_current_resolution()
            else:
                width, height = resolution.split("x")
            arguments += ["-fs-width", "%s" % width, "-fs-height", "%s" % height]

        if self.runner_config.get("machine"):
            arguments.append("-%s" % self.runner_config["machine"])

        bios_path = self.runner_config.get("bios_path")
        if not system.path_exists(bios_path):
            raise MissingBiosError()
        good_bios = self.find_good_bioses(bios_path)
        for bios, filename in good_bios.items():
            arguments.append("-%s" % bios)
            arguments.append(os.path.join(bios_path, filename))

        rom = self.game_config.get("main_file") or ""
        if not system.path_exists(rom):
            raise MissingGameExecutableError(filename=rom)
        arguments.append(rom)

        return {"command": arguments}
