#    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 .. import helpers
from . import ui_list

def _draw_alert_prop(layout, props, the_prop, cam_type, alert_cam="", min=None, max=None, **kwargs):
    can_alert = not alert_cam or alert_cam == cam_type
    if can_alert:
        value = getattr(props, the_prop)
        if min is not None and value < min:
            layout.alert = True
        if max is not None and value > max:
            layout.alert = True
        layout.prop(props, the_prop, **kwargs)
        layout.alert = False
    else:
        layout.prop(props, the_prop, **kwargs)

def _draw_gated_prop(layout, props, gate_prop, actual_prop):
    row = layout.row(align=True)
    row.prop(props, gate_prop, text="")
    row = row.row(align=True)
    row.active = getattr(props, gate_prop)
    row.prop(props, actual_prop)

def draw_camera_manipulation_props(layout, cam_type, props):
    # Camera Panning
    split = layout.split()
    col = split.column()
    col.label("Limit Panning:")
    col.prop(props, "x_pan_angle")
    col.prop(props, "y_pan_angle")

    # Camera Zoom
    col = split.column()
    col.label("Field of View:")
    col.prop(props, "fov")
    _draw_gated_prop(col, props, "limit_zoom", "zoom_min")
    _draw_gated_prop(col, props, "limit_zoom", "zoom_max")
    _draw_gated_prop(col, props, "limit_zoom", "zoom_rate")

def draw_camera_mode_props(layout, cam_type, props):
    # Point of Attention
    split = layout.split()
    col = split.column()
    col.label("Camera Mode:")
    col = col.column()
    col.alert = cam_type != "fixed" and props.poa_type == "none"
    col.prop(props, "poa_type", text="")
    col.alert = False
    row = col.row()
    row.active = props.poa_type == "object"
    row.prop(props, "poa_object", text="")
    col.separator()
    col.prop(props, "primary_camera")

    # Miscellaneous
    col = split.column()
    col.label("Tracking Settings:")
    col_follow = col.column()
    col_follow.active = cam_type == "follow"
    col_follow.prop(props, "maintain_los")
    col_follow.prop(props, "fall_vertical")
    col_follow.prop(props, "fast_run")
    col_target = col.column()
    col_target.active = props.poa_type != "none"
    col_target.prop(props, "ignore_subworld")

def draw_camera_poa_props(layout, cam_type, props):
    trans = props.transition

    # PoA Tracking
    split = layout.split()
    col = split.column()
    col.label("Default Tracking Transition:")
    col.prop(trans, "poa_acceleration", text="Acceleration")
    col.prop(trans, "poa_deceleration", text="Deceleration")
    col.prop(trans, "poa_velocity", text="Maximum Velocity")
    col = col.column()
    col.active = cam_type in {"firstperson", "follow"}
    col.prop(trans, "poa_cut", text="Cut Animation")

    # PoA Offset
    col = split.column()
    col.label("Point of Attention Offset:")
    col.prop(props, "poa_offset", text="")
    col.prop(props, "poa_worldspace")

def draw_camera_pos_props(layout, cam_type, props):
    trans = props.transition

    # Position Tracking (only for follow cams)
    split = layout.split()
    col = split.column()

    # Position Transitions
    col.active = cam_type != "circle"
    col.label("Default Position Transition:")
    _draw_alert_prop(col, trans, "pos_acceleration", cam_type,
                     alert_cam="rail", max=10.0, text="Acceleration")
    _draw_alert_prop(col, trans, "pos_deceleration", cam_type,
                     alert_cam="rail", max=10.0, text="Deceleration")
    _draw_alert_prop(col, trans, "pos_velocity", cam_type,
                     alert_cam="rail", max=10.0, text="Maximum Velocity")
    col = col.column()
    col.active = cam_type in {"firstperson", "follow"}
    col.prop(trans, "pos_cut", text="Cut Animation")

    # Position Offsets
    col = split.column()
    col.active = cam_type in {"firstperson", "follow"}
    col.label("Position Offset:")
    col.prop(props, "pos_offset", text="")
    col.prop(props, "pos_worldspace")

def draw_circle_camera_props(layout, props):
    # Circle Camera Stuff
    layout.prop(props, "circle_center")
    layout.prop(props, "circle_pos")
    layout.prop(props, "circle_velocity")
    row = layout.row(align=True)
    row.active = props.circle_center is None
    row.prop(props, "circle_radius_ui")

class CameraButtonsPanel:
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "data"

    @classmethod
    def poll(cls, context):
        return (context.camera and context.scene.render.engine == "PLASMA_GAME")


class PlasmaCameraTypePanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = ""
    bl_options = {"HIDE_HEADER"}

    def draw(self, context):
        camera = context.camera.plasma_camera
        self.layout.prop(camera, "camera_type")


class PlasmaCameraModePanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Camera Tracking"

    def draw(self, context):
        camera = context.camera.plasma_camera
        draw_camera_mode_props(self.layout, camera.camera_type, camera.settings)


class PlasmaCameraAttentionPanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Point of Attention Tracking"

    def draw(self, context):
        camera = context.camera.plasma_camera
        draw_camera_poa_props(self.layout, camera.camera_type, camera.settings)


class PlasmaCameraPositionPanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Position Tracking"

    def draw(self, context):
        camera = context.camera.plasma_camera
        draw_camera_pos_props(self.layout, camera.camera_type, camera.settings)


class PlasmaCameraCirclePanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Circle Camera"

    def draw(self, context):
        camera = context.camera.plasma_camera
        draw_circle_camera_props(self.layout, camera.settings)

    @classmethod
    def poll(cls, context):
        return super().poll(context) and context.camera.plasma_camera.camera_type == "circle"


class PlasmaCameraAnimationPanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Camera Animation"
    bl_options = {"DEFAULT_CLOSED"}

    def draw(self, context):
        layout = self.layout
        camera = context.camera.plasma_camera
        props = camera.settings

        split = layout.split()
        col = split.column()
        col.label("Animation:")
        anim_enabled = props.anim_enabled or context.object.plasma_modifiers.animation.enabled
        col.active = anim_enabled and context.object.plasma_object.has_animation_data
        col.prop(props, "start_on_push")
        col.prop(props, "stop_on_pop")
        col.prop(props, "reset_on_pop")

        col = split.column()
        col.active = camera.camera_type == "rail"
        invalid = camera.camera_type == "rail" and not context.object.plasma_object.has_transform_animation
        col.alert = invalid
        col.label("Rail:")
        col.prop(props, "rail_pos", text="")
        if invalid:
            col.label("Rail cameras must have a transformation animation!", icon="ERROR")

    def draw_header(self, context):
        self.layout.active = context.object.plasma_object.has_animation_data
        if not context.object.plasma_modifiers.animation.enabled:
            self.layout.prop(context.camera.plasma_camera.settings, "anim_enabled", text="")


class PlasmaCameraViewPanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Camera Lens"

    def draw(self, context):
        camera = context.camera.plasma_camera
        draw_camera_manipulation_props(self.layout, camera.camera_type, camera.settings)


class TransitionListUI(bpy.types.UIList):
    def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
        if item.camera is None:
            layout.label("[Default Transition]")
        else:
            layout.label(item.camera.name, icon="CAMERA_DATA")
        layout.prop(item, "enabled", text="")


class PlasmaCameraTransitionPanel(CameraButtonsPanel, bpy.types.Panel):
    bl_label = "Transitions"

    def draw(self, context):
        layout = self.layout
        camera = context.camera.plasma_camera

        ui_list.draw_list(layout, "TransitionListUI", "camera", camera, "transitions",
                          "active_transition_index", rows=3, maxrows=4)

        try:
            item = camera.transitions[camera.active_transition_index]
            trans = item.transition
        except:
            pass
        else:
            layout.separator()
            box = layout.box()
            box.prop(item, "camera", text="Transition From")
            box.prop(item, "mode")

            box.separator()
            split = box.split()
            split.active = item.mode == "manual"

            col = split.column()
            col.label("Tracking Transition:")
            col.prop(trans, "poa_acceleration", text="Acceleration")
            col.prop(trans, "poa_deceleration", text="Deceleration")
            col.prop(trans, "poa_velocity", text="Maximum Velocity")
            col.prop(trans, "poa_cut", text="Cut Transition")

            col = split.column()
            col.label("Position Transition:")
            col.prop(trans, "pos_acceleration", text="Acceleration")
            col.prop(trans, "pos_deceleration", text="Deceleration")
            col.prop(trans, "pos_velocity", text="Maximum Velocity")
            col.prop(trans, "pos_cut", text="Cut Transition")
