bl_info = {
    "name": "Execute Python from Clipboard",
    "author": "Greenface", 
    "version": (2, 0),
    "blender": (4, 2, 0),
    "location": "Preferences > Add-ons",
    "description": "Executes the Python script from the OS clipboard when a hotkey is pressed.",
    "category": "Development",
}

import bpy
import os

addon_keymaps = []
addon_name = os.path.splitext(os.path.basename(__file__))[0]

def update_hotkey(self, context):
    unregister_keymaps()
    register_keymaps()

class ExecuteClipboardScriptOperator(bpy.types.Operator):
    bl_idname = "wm.execute_clipboard_script"
    bl_label = "Execute Clipboard Script"

    def execute(self, context):
        text = context.window_manager.clipboard

        # Execute the text as a Python script
        try:
            exec(text, {'bpy': bpy, '__builtins__': __builtins__})
        except Exception as e:
            self.report({'ERROR'}, str(e))
            return {'CANCELLED'}

        return {'FINISHED'}

class ExecuteClipboardScriptPreferences(bpy.types.AddonPreferences):
    bl_idname = addon_name

    # Key selection
    key: bpy.props.EnumProperty(
        name="",
        items=[
            (item.identifier, item.name, item.description)
            for item in bpy.types.Event.bl_rna.properties['type'].enum_items
            if item.identifier not in {'NONE', 'TIMER'}
        ],
        default='F5',
        update=update_hotkey
    )

    # Modifier keys as BoolProperties
    shift: bpy.props.BoolProperty(
        name="Shift",
        description="Shift key",
        default=False,
        update=update_hotkey
    )
    ctrl: bpy.props.BoolProperty(
        name="Ctrl",
        description="Control key",
        default=False,
        update=update_hotkey
    )
    alt: bpy.props.BoolProperty(
        name="Alt",
        description="Alt key",
        default=False,
        update=update_hotkey
    )

    def draw(self, context):
        layout = self.layout

        # Main box for "Set Hotkey"
        main_box = layout.box()
        main_box.label(text="Set Hotkey")

        # Box for "Key" and its dropdown
        key_box = main_box.box()
        key_row = key_box.row()
        key_split = key_row.split(factor=0.3)
        key_split.label(text="Key")
        key_split.prop(self, "key", text="")

        # Box for "Modifiers" and the buttons
        modifier_box = main_box.box()
        modifier_row = modifier_box.row()
        modifier_split = modifier_row.split(factor=0.3)
        modifier_split.label(text="Modifiers")
        modifier_control = modifier_split.row(align=True)
        # Add buttons with names "Shift", "Ctrl", and "Alt"
        modifier_control.prop(self, "shift", toggle=True)
        modifier_control.prop(self, "ctrl", toggle=True)
        modifier_control.prop(self, "alt", toggle=True)

    def update_hotkey(self, context):
        update_hotkey(self, context)

def register_keymaps():
    prefs = bpy.context.preferences.addons.get(addon_name)
    if not prefs:
        return
    prefs = prefs.preferences

    wm = bpy.context.window_manager

    # Remove existing keymap items for our operator
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

    # Determine modifier keys
    shift = prefs.shift
    ctrl = prefs.ctrl
    alt = prefs.alt

    # Add new keymap item
    if prefs.key != 'NONE':
        km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY', region_type='WINDOW')
        kmi = km.keymap_items.new('wm.execute_clipboard_script', type=prefs.key, value='PRESS',
                                  shift=shift, ctrl=ctrl, alt=alt)
        addon_keymaps.append((km, kmi))

def unregister_keymaps():
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

def register():
    bpy.utils.register_class(ExecuteClipboardScriptOperator)
    bpy.utils.register_class(ExecuteClipboardScriptPreferences)
    register_keymaps()

def unregister():
    unregister_keymaps()
    bpy.utils.unregister_class(ExecuteClipboardScriptOperator)
    bpy.utils.unregister_class(ExecuteClipboardScriptPreferences)

if __name__ == "__main__":
    register()
