#    This file is part of Korman.
#
#    Korman is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Korman is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Korman.  If not, see <http://www.gnu.org/licenses/>.

import bpy
from bpy.props import *
from . import korlib

game_versions = [("pvPrime", "Ages Beyond Myst (63.11)", "Targets the original Uru (Live) game"),
                 ("pvPots", "Path of the Shell (63.12)", "Targets the most recent offline expansion pack"),
                 ("pvMoul", "Myst Online: Uru Live (70)", "Targets the most recent online game")]

class PlasmaGame(bpy.types.PropertyGroup):
    name = StringProperty(name="Name",
                          description="Name of the Plasma Game",
                          options=set())
    path = StringProperty(name="Path",
                          description="Path to this Plasma Game",
                          options=set())
    version = EnumProperty(name="Version",
                           description="Plasma version of this game",
                           items=game_versions,
                           options=set())

    player = StringProperty(name="Player",
                            description="Name of the player to use when launching the game",
                            options=set())
    ki = IntProperty(name="KI",
                     description="KI Number of the player to use when launching the game",
                     options=set(), min=0)
    serverini = StringProperty(name="Server INI",
                               description="Name of the server configuation to use when launching the game",
                               options=set())

    @property
    def can_launch(self):
        if self.version == "pvMoul":
            return self.is_property_set("ki") and self.ki
        else:
            return self.is_property_set("player") and bool(self.player.strip())


class KormanAddonPreferences(bpy.types.AddonPreferences):
    bl_idname = __package__

    games = CollectionProperty(type=PlasmaGame)
    active_game_index = IntProperty(options={"SKIP_SAVE"})

    def _check_py22_exe(self, context):
        if self._ensure_abspath((2, 2)):
            self._check_python((2, 2))
    def _check_py23_exe(self, context):
        if self._ensure_abspath((2, 3)):
            self._check_python((2, 3))
    def _check_py27_exe(self, context):
        if self._ensure_abspath((2, 7)):
            self._check_python((2, 7))

    python22_executable = StringProperty(name="Python 2.2",
                                         description="Path to the Python 2.2 executable",
                                         options=set(),
                                         subtype="FILE_PATH",
                                         update=_check_py22_exe)
    python23_executable = StringProperty(name="Python 2.3",
                                         description="Path to the Python 2.3 executable",
                                         options=set(),
                                         subtype="FILE_PATH",
                                         update=_check_py23_exe)
    python27_executable = StringProperty(name="Python 2.7",
                                         description="Path to the Python 2.7 executable",
                                         options=set(),
                                         subtype="FILE_PATH",
                                         update=_check_py27_exe)

    def _validate_py_exes(self):
        if not self.is_property_set("python22_valid"):
            self._check_python((2, 2))
        if not self.is_property_set("python23_valid"):
            self._check_python((2, 3))
        if not self.is_property_set("python27_valid"):
            self._check_python((2, 7))
        return True

    # Internal error states
    python22_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
    python23_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
    python27_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
    python_validated = BoolProperty(get=_validate_py_exes, options={"HIDDEN", "SKIP_SAVE"})

    def _check_python(self, py_version):
        py_exe = getattr(self, "python{}{}_executable".format(*py_version))
        if py_exe:
            valid = korlib.verify_python(py_version, py_exe)
        else:
            valid = True
        setattr(self, "python{}{}_valid".format(*py_version), valid)

    def _ensure_abspath(self, py_version):
        attr = "python{}{}_executable".format(*py_version)
        path = getattr(self, attr)
        if path.startswith("//"):
            setattr(self, attr, bpy.path.abspath(path))
            return False
        return True

    def draw(self, context):
        layout = self.layout
        split = layout.split()
        main_col = split.column()

        main_col.label("Plasma Games:")
        row = main_col.row()
        row.template_list("PlasmaGameListRW", "games", self, "games", self,
                          "active_game_index", rows=3)
        col = row.column(align=True)
        col.operator("world.plasma_game_add", icon="ZOOMIN", text="")
        col.operator("world.plasma_game_remove", icon="ZOOMOUT", text="")
        col.operator("world.plasma_game_convert", icon="IMPORT", text="")

        # Game Properties
        active_game_index = self.active_game_index
        if bool(self.games) and active_game_index < len(self.games):
            active_game = self.games[active_game_index]

            col = split.column()
            col.label("Game Configuration:")
            box = col.box().column()

            row = box.row(align=True)
            row.prop(active_game, "path")
            op = row.operator("world.plasma_game_add", icon="FILE_FOLDER", text="")
            op.filepath = active_game.path
            op.game_index = active_game_index
            box.prop(active_game, "version")

            box.separator()
            box.separator()
            if active_game.version == "pvMoul":
                box.alert = not active_game.is_property_set("ki")
                box.prop(active_game, "ki", slider=False)
                box.alert = False
                box.prop(active_game, "serverini")
            else:
                box.alert = not active_game.is_property_set("player")
                box.prop(active_game, "player")

        # Python Installs
        assert self.python_validated
        col = layout.column()
        col.label("Python Executables:")
        col.alert = not self.python22_valid
        col.prop(self, "python22_executable")
        col.alert = not self.python23_valid
        col.prop(self, "python23_executable")
        col.alert = not self.python27_valid
        col.prop(self, "python27_executable")

    @classmethod
    def register(cls):
        # Register the old-timey per-world Plasma Games for use in the conversion
        # operator. What fun. I guess....
        from .properties.prop_world import PlasmaGames
        PlasmaGames.games = CollectionProperty(type=PlasmaGame)
