# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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.
#

import os
import bpy
from enum import Enum
from bpy.props import FloatVectorProperty, StringProperty, PointerProperty
import math
from mathutils import Vector
from bpy_extras.image_utils import load_image
from . import turok_object_panel
from . import kex_utils
from . import turok_preferences

# -----------------------------------------------------------------------------
#
class TurokSceneSoundsPropGroup(bpy.types.PropertyGroup):
    filename: bpy.props.StringProperty(name="", default="", subtype="FILE_NAME")
    path: bpy.props.StringProperty(name="", default="", subtype="FILE_PATH")
#end class

# -----------------------------------------------------------------------------
#
class TUROK_UL_scene_sound_props(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
        row = layout.row()
        row.label(text=item.filename, translate=False)
    #end func
#end class

# -----------------------------------------------------------------------------
#
class TurokSceneSettings(bpy.types.PropertyGroup):
    def on_sound_folder_changed(self, context):
        absPath = os.path.abspath(self.soundFolder)
        if os.path.isdir(absPath):
            self.sounds.clear()
            with os.scandir(absPath) as it:
                for entry in it:
                    if entry.is_file(follow_symlinks=False):
                        filename, ext = os.path.splitext(entry.name)
                        if ext == ".ksnd":
                            soundItem = self.sounds.add()
                            soundItem.name = filename
                            soundItem.filename = filename
                            soundItem.path = entry.path
                        #end if
                    #end if
                #end for
            #end with
        #end if
    #end func
    
    def on_sound_index_changed(self, context):
        if self.soundIndex >= 0 and self.soundIndex < len(self.sounds):
            kex_utils.stop_sound()
            kex_utils.play_ksnd(self.sounds[self.soundIndex].path, False)
        #end if
    #end func
        
    sounds: bpy.props.CollectionProperty(name="Sounds", type = TurokSceneSoundsPropGroup)
    soundIndex: bpy.props.IntProperty(name="", default = -1, update=on_sound_index_changed)
    soundTestID: bpy.props.IntProperty(name="Sound ID", default = 2)
    showSoundTest: bpy.props.BoolProperty(default=False)
    soundFolder : StringProperty(name="", description="", subtype="DIR_PATH", update=on_sound_folder_changed)
#end class

# -----------------------------------------------------------------------------
#
class TUROK_PT_tools(bpy.types.Panel):
    bl_label = "Turok Tools"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Turok"
    
    def draw(self, context):
        scene = context.scene
        layout = self.layout
        
        if scene is None:
            return
                
        row = layout.row(align=True)
        row.alignment = 'CENTER'
        row.operator(turok_preferences.TUROK_OT_pref_open_readme.bl_idname, icon='HELP', text="View Readme")
        row.operator(turok_preferences.TUROK_OT_pref_open_addon_folder.bl_idname, icon='FILE_FOLDER', text="")
        box = layout.box()
        row = layout.row()
        row.operator(TUROK_OT_scene_setup_player_model.bl_idname, icon='HELP', text="Setup Player Model Scale")
        row = layout.row()
        row.operator(TUROK_OT_scene_setup_weapon_model.bl_idname, icon='HELP', text="Setup Weapon Model Scale")
        row = layout.row()
        row.operator(TUROK_OT_scene_setup_weapon_camera.bl_idname, icon='HELP', text="Setup Weapon Camera")
        box = layout.box()
        row = layout.row()
        row.prop(scene.t1, "showSoundTest", icon="TRIA_DOWN" if scene.t1.showSoundTest else "TRIA_RIGHT", icon_only=True, emboss=False)
        soundTestText = "Sound Test"
        if scene.t1.showSoundTest:
            soundTestText = "Sound Test (%d)" % (len(scene.t1.sounds))
        row.label(text=soundTestText, icon="PLAY_SOUND", translate=False)
        if scene.t1.showSoundTest:
            box = layout.box()
            row = box.row()
            row.prop(scene.t1, "soundFolder")
            row = box.row()
            row.template_list('TUROK_UL_scene_sound_props', "TurokSceneSoundsPropGroup", scene.t1, "sounds", scene.t1, "soundIndex")
            row = layout.row(align=True)
            row.prop(scene.t1, "soundTestID", text="")
            row.separator()
            row.operator(turok_object_panel.TUROK_OT_play_sound_id.bl_idname, icon='PLAY', text="").soundID = scene.t1.soundTestID
            row.operator(turok_object_panel.TUROK_OT_stop_all_sounds.bl_idname, icon='PAUSE', text="")
            row.separator()
            row.operator(TUROK_OT_scene_sound_list.bl_idname, icon='COLLAPSEMENU', text="")
            row = layout.row()
            row.label(text=kex_utils.get_sound_desc(scene.t1.soundTestID))
        #end if
    #end func
#end class

# -----------------------------------------------------------------------------
#
class TUROK_OT_scene_sound_list(bpy.types.Operator):
    """Set SoundID with sound list"""
    bl_idname = "turok_scene.test_sound_list"
    bl_label = "Set SoundID with sound list"
    bl_options = {'UNDO'}
    bl_property = "enumprop"
    
    def items_cb(self, context):
        items = []
        for id in kex_utils.turok1Defs["sounds"]:
            action = kex_utils.turok1Defs["sounds"][id]
            items.append((action["description"], action["description"], "", action["id"]))
        return items
    
    enumprop: bpy.props.EnumProperty(items=items_cb)

    @classmethod
    def poll(cls, context):
        return context.scene is not None and "sounds" in kex_utils.turok1Defs
    #end func
        
    def execute(self, context):
        props = context.scene.t1
        props.soundTestID = kex_utils.get_enum_type(self.items_cb(context), self.enumprop)
        kex_utils.stop_sound()
        kex_utils.play_ksnd(kex_utils.get_sound_path(props.soundTestID))
        return {'FINISHED'}
    #end func

    def invoke(self, context, event):
        context.window_manager.invoke_search_popup(self)
        return {'FINISHED'}
    #end func
#end class

# -----------------------------------------------------------------------------
#
class TUROK_OT_scene_setup_player_model(bpy.types.Operator):
    bl_idname = "turok_scene.setup_player_model"
    bl_label = "Setup Player Model"
    bl_description = "Creates a box object that is the same scale as Turok"
    bl_options = {'UNDO'}
    
    def execute(self, context):
        playerObj = kex_utils.get_object(kex_utils.turok1PlayerScaleName)
        if playerObj is None:
            playerObj = kex_utils.create_cube(kex_utils.turok1PlayerScaleName, Vector((-30.72, -30.72, 0.0)), Vector((30.72, 30.72, 71.68)), True)
        #end if
            
        return {'FINISHED'}
    #end func
#end class

# -----------------------------------------------------------------------------
#
class TUROK_OT_scene_setup_weapon_model(bpy.types.Operator):
    bl_idname = "turok_scene.setup_weapon_model"
    bl_label = "Setup Weapon Model"
    bl_description = "Creates a box object that is the same scale as a Weapon"
    bl_options = {'UNDO'}
    
    def execute(self, context):
        weaponObj = kex_utils.get_object(kex_utils.turok1WeaponScaleName)
        if weaponObj is None:
            weaponObj = kex_utils.create_cube(kex_utils.turok1WeaponScaleName, Vector((-67.0758, -302.145, -78.1183)), Vector((-36.0192, 0.0, -40.5939)), True)
        #end if
            
        return {'FINISHED'}
    #end func
#end class

# -----------------------------------------------------------------------------
#
class TUROK_OT_scene_setup_weapon_camera(bpy.types.Operator):
    bl_idname = "turok_scene.setup_weapon_cam"
    bl_label = "Setup Weapon Camera"
    bl_description = "Creates a camera object that has the same settings as the TurokEX camera"
    bl_options = {'UNDO'}
    
    def execute(self, context):
        camObj = kex_utils.get_object(kex_utils.turok1WeaponCamName)
        if camObj is None:
            #create camera data
            cam = bpy.data.cameras.get(kex_utils.turok1WeaponCamName)
            if cam is None:
                cam = bpy.data.cameras.new(kex_utils.turok1WeaponCamName)
            camObj = kex_utils.create_turok_object(kex_utils.turok1WeaponCamName, cam, "NONE", rotMode="XYZ")
        #end if
        
        if camObj.type == "CAMERA":
            #setup scene
            scene = context.scene
            scene.render.resolution_x = 1920
            scene.render.resolution_y = 1080
            scene.render.pixel_aspect_x = 1.0
            scene.render.pixel_aspect_y = 1.0
            
            #setup camera properties
            cam = camObj.data
            camObj.rotation_euler = (math.radians(90.0), 0.0, math.radians(180))
            camObj.scale = (200.0, 200.0, 200.0)
            camObj.lock_location = (True, True, True)
            camObj.lock_rotation = (True, True, True)
            cam.clip_end = 10000
            cam.sensor_width = 35.0
            cam.lens_unit = "FOV"
            cam.angle = math.atan((scene.render.resolution_x * 0.5) / (scene.render.resolution_y * 0.5 / math.tan(math.radians(kex_utils.T1WEAPON_FOV) * 0.5))) * 2.0
            cam.show_background_images = True
            #setup background image
            if len(cam.background_images) <= 0:
                camImageBack = cam.background_images.new()
            else:
                camImageBack = cam.background_images[0]
            #end if
            camImageBack.image = load_image(os.path.join(kex_utils.addon_texture_dir(), "t1_camera_bg_back.jpg"), check_existing=True)
            camImageBack.alpha = 1.0
            camImageBack.display_depth = 'BACK'
            
            #setup foreground image
            if len(cam.background_images) <= 1:
                camImageFront = cam.background_images.new()
            else:
                camImageFront = cam.background_images[1]
            #end if
            camImageFront.image = load_image(os.path.join(kex_utils.addon_texture_dir(), "t1_camera_bg_front.png"), check_existing=True)
            camImageFront.alpha = 0.7
            camImageFront.display_depth = 'FRONT'
        #end if
            
        return {'FINISHED'}
    #end func
#end class

# -----------------------------------------------------------------------------
#
def register():
    bpy.utils.register_class(TurokSceneSoundsPropGroup)
    bpy.utils.register_class(TUROK_UL_scene_sound_props)
    bpy.utils.register_class(TurokSceneSettings)
    bpy.utils.register_class(TUROK_PT_tools)
    bpy.utils.register_class(TUROK_OT_scene_sound_list)
    bpy.utils.register_class(TUROK_OT_scene_setup_player_model)
    bpy.utils.register_class(TUROK_OT_scene_setup_weapon_model)
    bpy.utils.register_class(TUROK_OT_scene_setup_weapon_camera)
    bpy.types.Scene.t1 = bpy.props.PointerProperty(type=TurokSceneSettings)
#end func

# -----------------------------------------------------------------------------
#     
def unregister():
    bpy.utils.unregister_class(TurokSceneSoundsPropGroup)
    bpy.utils.unregister_class(TUROK_UL_scene_sound_props)
    bpy.utils.unregister_class(TurokSceneSettings)
    bpy.utils.unregister_class(TUROK_PT_tools)
    bpy.utils.unregister_class(TUROK_OT_scene_sound_list)
    bpy.utils.unregister_class(TUROK_OT_scene_setup_player_model)
    bpy.utils.unregister_class(TUROK_OT_scene_setup_weapon_model)
    bpy.utils.unregister_class(TUROK_OT_scene_setup_weapon_camera)
    del bpy.types.Scene.t1
#end func
