# ##### BEGIN GPL LICENSE BLOCK #####
#
#  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.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

import bpy

bl_info = {
    "name": "UI Animation Render",
    "author": "Luca Rood",
    "description": "Render animations of the Blender UI.",
    "blender": (2, 80, 0),
    "version": (0, 1, 0),
    "location": "View3D > Sidebar > View Tab and Ctrl+Shift+F12",
    "warning": "",
    "category": "Render"
}

km = None


def draw_ui(prefs, layout):
    layout.prop(prefs, "delay")

    col = layout.column(align=True)
    col.label(text="Animation Highlight:")

    row = col.row()
    row.prop(prefs, "anim_highlight", expand=True)

    if prefs.anim_highlight == "replace":
        split = col.split(factor=0.2)
        split.label(text="Color")
        row = split.row(align=True)
        row.prop(prefs, "highlight_color", text="")
        row.prop(prefs, "highlight_blend", text="Blend")


class UIAnimationRenderPreferences(bpy.types.AddonPreferences):
    bl_idname = __name__

    delay: bpy.props.FloatProperty(
        name="Capture Delay",
        description="How much time to wait (seconds) before capturing each frame, to allow the viewport to clean up",
        default=0.5
    )

    anim_highlight: bpy.props.EnumProperty(
        name="Animation Highlight",
        description="What to do with the animated field highlight color",
        items=[("keep", "Keep", "Keep the animated field highlight", 0),
               ("hide", "Hide", "Hide the animated field highlight", 1),
               ("replace", "Replace", "Replace the animated field highlight", 2)],
        default="keep"
    )

    highlight_color: bpy.props.FloatVectorProperty(
        name="Highlight Color",
        description="Color to use for animated field highlights",
        subtype='COLOR',
        default=(1.0, 1.0, 1.0)
    )

    highlight_blend: bpy.props.FloatProperty(
        name="Highlight Blend",
        description="How much the highlight color influences the field color",
        default=0.5
    )

    def draw(self, context):
        draw_ui(self, self.layout)


class RenderScreen(bpy.types.Operator):
    bl_idname = "render.render_screen"
    bl_label = "Render Screen"
    bl_description = "Capture the screen for each animation frame and write to the render output path"

    _timer = None
    _f_initial = 1
    _theme_blend = 0.0
    _theme_key = (0, 0, 0)
    _theme_key_sel = (0, 0, 0)
    _theme_anim = (0, 0, 0)
    _theme_anim_sel = (0, 0, 0)
    _theme_driven = (0, 0, 0)
    _theme_driven_sel = (0, 0, 0)

    def modal(self, context, event):
        if event.type in {'RIGHTMOUSE', 'ESC'}:
            self.stop(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            scene = context.scene
            f_curr = scene.frame_current

            bpy.ops.screen.screenshot(filepath=context.scene.render.frame_path(frame=f_curr))

            if f_curr < scene.frame_end:
                scene.frame_set(f_curr + 1)
            else:
                self.stop(context)
                return {'FINISHED'}

        return {'RUNNING_MODAL'}

    def execute(self, context):
        # Adjust animation highlight (theme)
        prefs = context.preferences
        addon_prefs = prefs.addons[__name__].preferences
        theme = prefs.themes[0].user_interface.wcol_state

        if addon_prefs.anim_highlight == "hide":
            self._theme_blend = theme.blend
            theme.blend = 0.0
        elif addon_prefs.anim_highlight == "replace":
            self._theme_blend = theme.blend
            self._theme_key = theme.inner_key.copy()
            self._theme_key_sel = theme.inner_key_sel.copy()
            self._theme_anim = theme.inner_anim.copy()
            self._theme_anim_sel = theme.inner_anim_sel.copy()
            self._theme_driven = theme.inner_driven.copy()
            self._theme_driven_sel = theme.inner_driven_sel.copy()

            theme.blend = addon_prefs.highlight_blend
            theme.inner_key = addon_prefs.highlight_color
            theme.inner_key_sel = addon_prefs.highlight_color
            theme.inner_anim = addon_prefs.highlight_color
            theme.inner_anim_sel = addon_prefs.highlight_color
            theme.inner_driven = addon_prefs.highlight_color
            theme.inner_driven_sel = addon_prefs.highlight_color

        # Set frame
        scene = context.scene
        self._f_initial = scene.frame_current
        scene.frame_set(scene.frame_start)

        # Start timer
        wm = context.window_manager
        self._timer = wm.event_timer_add(addon_prefs.delay, window=context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def stop(self, context):
        # Stop timer
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

        # Reset frame
        context.scene.frame_set(self._f_initial)

        # Reset theme
        prefs = context.preferences
        addon_prefs = prefs.addons[__name__].preferences
        theme = prefs.themes[0].user_interface.wcol_state

        if addon_prefs.anim_highlight == "hide":
            theme.blend = self._theme_blend
        elif addon_prefs.anim_highlight == "replace":
            theme.blend = self._theme_blend
            theme.inner_key = self._theme_key
            theme.inner_key_sel = self._theme_key_sel
            theme.inner_anim = self._theme_anim
            theme.inner_anim_sel = self._theme_anim_sel
            theme.inner_driven = self._theme_driven
            theme.inner_driven_sel = self._theme_driven_sel


class VIEW3D_PT_ui_animation_render(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "View"
    bl_label = "UI Animation Render"
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = False

        prefs = context.preferences
        addon_prefs = prefs.addons[__name__].preferences

        layout.operator(RenderScreen.bl_idname)
        draw_ui(addon_prefs, layout)


def register():
    global km

    bpy.utils.register_class(UIAnimationRenderPreferences)
    bpy.utils.register_class(RenderScreen)
    bpy.utils.register_class(VIEW3D_PT_ui_animation_render)

    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Screen', space_type='EMPTY')
    km.keymap_items.new('render.render_screen', 'F12', 'PRESS', shift=True, ctrl=True)


def unregister():
    global km

    bpy.utils.unregister_class(UIAnimationRenderPreferences)
    bpy.utils.unregister_class(RenderScreen)
    bpy.utils.unregister_class(VIEW3D_PT_ui_animation_render)

    if km is not None:
        wm = bpy.context.window_manager
        wm.keyconfigs.addon.keymaps.remove(km)
        km = None
