# Standard Library
from gettext import gettext as _
from os import path

# Lutris Modules
from lutris.runners.runner import Runner


class easyrpg(Runner):
    human_name = _("EasyRPG Player")
    description = _("Runs RPG Maker 2000/2003 games")
    platforms = [_("Linux")]
    runnable_alone = True
    entry_point_option = "project_path"
    runner_executable = "easyrpg/easyrpg-player"
    download_url = "https://easyrpg.org/downloads/player/0.7.0/easyrpg-player-0.7.0-linux.tar.gz"

    game_options = [
        {
            "option": "project_path",
            "type": "directory_chooser",
            "label": _("Game directory"),
            "help": _("Select the directory of the game. (required)")
        },
        {
            "option": "encoding",
            "type": "string",
            "label": _("Encoding"),
            "help": _(
                "Instead of auto detecting the encoding or using the "
                "one in RPG_RT.ini, the specified encoding is used. "
                "Use 'auto' for automatic detection."
            )
        },
        {
            "option": "engine",
            "type": "choice",
            "label": _("Engine"),
            "help": _("Disable auto detection of the simulated engine."),
            "choices": [
                (_("Auto"), ""),
                (_("RPG Maker 2000 engine (v1.00 - v1.10)"), "rpg2k"),
                (_("RPG Maker 2000 engine (v1.50 - v1.51)"), "rpg2kv150"),
                (_("RPG Maker 2000 (English release) engine"), "rpg2ke"),
                (_("RPG Maker 2003 engine (v1.00 - v1.04)"), "rpg2k3"),
                (_("RPG Maker 2003 engine (v1.05 - v1.09a)"), "rpg2k3v105"),
                (_("RPG Maker 2003 (English release) engine"), "rpg2k3e")
            ],
            "default": ""
        },
        {
            "option": "save_path",
            "type": "directory_chooser",
            "label": _("Save path"),
            "help": _(
                "Instead of storing save files in the game directory they "
                "are stored in the specified path. The directory must exist."
            )
        },
        {
            "option": "new_game",
            "type": "bool",
            "label": _("New game"),
            "help": _("Skip the title scene and start a new game directly."),
            "default": False
        },
        {
            "option": "load_game_id",
            "type": "range",
            "label": _("Load game ID"),
            "help": _(
                "Skip the title scene and load SaveXX.lsd. "
                "Set to '0' to disable."
            ),
            "min": 0,
            "max": 99,
            "default": 0
        },
        {
            "option": "start_map_id",
            "type": "range",
            "label": _("Start map ID"),
            "help": _(
                "Overwrite the map used for new games and use "
                "MapXXXX.lmu instead. Set to '0' to disable. "
                "\n\nIncompatible with 'Load game ID'."
            ),
            "min": 0,
            "max": 9999,
            "default": 0
        },
        {
            "option": "start_position",
            "type": "string",
            "label": _("Start position"),
            "help": _(
                "Overwrite the party start position and "
                "move the party to the specified position. "
                "Provide two numbers separated by a space. "
                "\n\nIncompatible with 'Load game ID'."
            )
        },
        {
            "option": "start_party",
            "type": "string",
            "label": _("Start party"),
            "help": _(
                "Overwrite the starting party members with "
                "the actors with the specified IDs. Provide "
                "one to four numbers separated by spaces. "
                "\n\nIncompatible with 'Load game ID'."
            )
        },
        {
            "option": "battle_test",
            "type": "string",
            "label": _("Monster party"),
            "help": _("Start a battle test with the specified monster party.")
        },
        {
            "option": "record_input",
            "type": "string",
            "label": _("Record input"),
            "help": _("Records all button input to the specified log file.")
        },
        {
            "option": "replay_input",
            "type": "file",
            "label": _("Replay input"),
            "help": _(
                "Replays button input from the specified log file, "
                "as generated by 'Record input'. If the RNG seed "
                "and the state of the save file directory is also "
                "the same as it was when the log was recorded, this "
                "should reproduce an identical run to the one recorded."
            )
        },
    ]

    runner_options = [
        {
            "option": "fullscreen",
            "type": "bool",
            "label": _("Fullscreen"),
            "help": _("Start in fullscreen mode."),
            "default": False
        },
        {
            "option": "audio",
            "type": "bool",
            "label": _("Enable audio"),
            "help": _(
                "Switch off to disable audio "
                "(in case you prefer your own music)."
            ),
            "default": True
        },
        {
            "option": "mouse",
            "type": "bool",
            "label": _("Enable mouse"),
            "help": _(
                "Use mouse click for decision and scroll wheel for lists."
            ),
            "default": False
        },
        {
            "option": "touch",
            "type": "bool",
            "label": _("Enable touch"),
            "help": _("Use one/two finger tap for decision/cancel."),
            "default": False
        },
        {
            "option": "hide_title",
            "type": "bool",
            "label": _("Hide title"),
            "help": _(
                "Hide the title background image and center the command menu."
            ),
            "default": False
        },
        {
            "option": "vsync",
            "type": "bool",
            "label": _("Enable VSync"),
            "help": _(
                "Switch off to disable VSync and use the FPS limit. "
                "VSync may or may not be supported on all platforms."
            ),
            "default": True
        },
        {
            "option": "fps_limit",
            "type": "string",
            "label": _("FPS limit"),
            "help": _(
                "Set a custom frames per second limit. If unspecified, "
                "the default is 60 FPS. Set to '0' to disable the frame "
                "limiter. This option may not be supported on all platforms."
            )
        },
        {
            "option": "show_fps",
            "type": "choice",
            "label": _("Show FPS"),
            "help": _("Enable frames per second counter."),
            "choices": [
                (_("Disabled"), "off"),
                (_("Fullscreen & title bar"), "on"),
                (_("Fullscreen, title bar & window"), "full")
            ],
            "default": "off"
        },
        {
            "option": "seed",
            "type": "string",
            "label": _("RNG seed"),
            "help": _("Seeds the random number generator")
        },
        {
            "option": "test_play",
            "type": "bool",
            "label": _("Test play"),
            "help": _("Enable TestPlay mode."),
            "default": False
        },
        {
            "option": "rtp",
            "type": "bool",
            "label": _("Enable RTP"),
            "help": _(
                "Switch off to disable support for the Runtime Package (RTP)."
            ),
            "default": True
        },
        {
            "option": "rpg2k_rtp_path",
            "type": "directory_chooser",
            "label": _("RPG2000 RTP location"),
            "help": _(
                "Full path to a directory containing an "
                "extracted RPG Maker 2000 Run-Time-Package (RTP)."
            )
        },
        {
            "option": "rpg2k3_rtp_path",
            "type": "directory_chooser",
            "label": _("RPG2003 RTP location"),
            "help": _(
                "Full path to a directory containing an "
                "extracted RPG Maker 2003 Run-Time-Package (RTP)."
            )
        },
        {
            "option": "rpg_rtp_path",
            "type": "directory_chooser",
            "label": _("Fallback RTP location"),
            "help": _("Full path to a directory containing a combined RTP.")
        },
    ]

    @property
    def game_path(self):
        game_path = self.game_data.get("directory")
        if game_path:
            return game_path

        # Default to the directory of the entry point
        entry_point = self.game_config.get(self.entry_point_option)
        if entry_point:
            return path.expanduser(entry_point)

        return ""

    def get_env(self, os_env=False, disable_runtime=False):
        env = super().get_env(os_env, disable_runtime=disable_runtime)

        rpg2k_rtp_path = self.runner_config.get("rpg2k_rtp_path")
        if rpg2k_rtp_path:
            env["RPG2K_RTP_PATH"] = rpg2k_rtp_path

        rpg2k3_rtp_path = self.runner_config.get("rpg2k3_rtp_path")
        if rpg2k3_rtp_path:
            env["RPG2K3_RTP_PATH"] = rpg2k3_rtp_path

        rpg_rtp_path = self.runner_config.get("rpg_rtp_path")
        if rpg_rtp_path:
            env["RPG_RTP_PATH"] = rpg_rtp_path

        return env

    def get_runner_command(self):
        cmd = [self.get_executable()]

        if self.runner_config["fullscreen"]:
            cmd.append("--fullscreen")
        else:
            cmd.append("--window")

        if not self.runner_config["audio"]:
            cmd.append("--disable-audio")

        if self.runner_config["mouse"]:
            cmd.append("--enable-mouse")

        if self.runner_config["touch"]:
            cmd.append("--enable-touch")

        if self.runner_config["hide_title"]:
            cmd.append("--hide-title")

        if not self.runner_config["vsync"]:
            cmd.append("--no-vsync")

        fps_limit = self.runner_config.get("fps_limit")
        if fps_limit:
            cmd.extend(("--fps-limit", fps_limit))

        show_fps = self.runner_config.get("show_fps")
        if show_fps != "off":
            cmd.append("--show-fps")
        if show_fps == "full":
            cmd.append("--fps-render-window")

        if self.runner_config["test_play"]:
            cmd.append("--test-play")

        seed = self.runner_config.get("seed")
        if seed:
            cmd.extend(("--seed", seed))

        if not self.runner_config["rtp"]:
            cmd.append("--disable-rtp")

        return cmd

    def get_run_data(self):
        cmd = self.get_runner_command()

        if self.default_path:
            game_path = path.expanduser(self.default_path)
            cmd.extend(("--project-path", game_path))

        return {"command": cmd, "env": self.get_env()}

    def play(self):
        if not self.game_path:
            return {"error": "CUSTOM", "text": _("No game directory provided")}
        if not path.isdir(self.game_path):
            return self.directory_not_found(self.game_path)

        cmd = self.get_runner_command()

        cmd.extend(("--project-path", self.game_path))

        encoding = self.game_config.get("encoding")
        if encoding:
            cmd.extend(("--encoding", encoding))

        engine = self.game_config.get("engine")
        if engine:
            cmd.extend(("--engine", engine))

        save_path = self.game_config.get("save_path")
        if save_path:
            save_path = path.expanduser(save_path)
            if not path.isdir(save_path):
                return self.directory_not_found(save_path)
            cmd.extend(("--save-path", save_path))

        record_input = self.game_config.get("record_input")
        if record_input:
            record_input = path.expanduser(record_input)
            cmd.extend(("--record-input", record_input))

        replay_input = self.game_config.get("replay_input")
        if replay_input:
            replay_input = path.expanduser(replay_input)
            if not path.isfile(replay_input):
                return {"error": "FILE_NOT_FOUND", "file": replay_input}
            cmd.extend(("--replay-input", replay_input))

        load_game_id = self.game_config.get("load_game_id")
        if load_game_id:
            cmd.extend(("--load-game-id", str(load_game_id)))

        start_map_id = self.game_config.get("start_map_id")
        if start_map_id:
            cmd.extend(("--start-map-id", str(start_map_id)))

        start_position = self.game_config.get("start_position")
        if start_position:
            cmd.extend(("--start-position", *start_position.split()))

        start_party = self.game_config.get("start_party")
        if start_party:
            cmd.extend(("--start-party", *start_party.split()))

        battle_test = self.game_config.get("battle_test")
        if battle_test:
            cmd.extend(("--battle-test", battle_test))

        return {"command": cmd}

    @staticmethod
    def directory_not_found(directory):
        error = _(
            "The directory {} could not be found"
        ).format(directory.replace("&", "&amp;"))
        return {"error": "CUSTOM", "text": error}
