bl_info = {
    "name": "Selection Cycle Custom",
    "author": "Michael Colina & Assistant",
    "version": (1, 4),
    "blender": (4, 3, 2),
    "location": "3D View",
    "description": "Customize and cycle selection tools with initial tool set on startup/file load.",
    "category": "3D View",
}

import bpy
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
from bpy.types import AddonPreferences
from bpy.props import BoolProperty, EnumProperty
from bpy.app.handlers import persistent


# 1. Preferences
class SELECTION_CYCLE_OT_preferences(AddonPreferences):
    bl_idname = __name__

    use_tweak: BoolProperty(
        name="Tweak",
        description="Include Tweak tool in cycle",
        default=True
    )
    use_select_box: BoolProperty(
        name="Select Box",
        description="Include Select Box tool in cycle",
        default=True
    )
    use_select_circle: BoolProperty(
        name="Select Circle",
        description="Include Select Circle tool in cycle",
        default=True
    )
    use_select_lasso: BoolProperty(
        name="Select Lasso",
        description="Include Select Lasso tool in cycle",
        default=True
    )

    default_tool: EnumProperty(
        name="Default Startup Tool",
        description="Tool set automatically when file/startup loads",
        items=[
            ('builtin.select_box', "Select Box", "Default to Select Box"),
            ('builtin.select_circle', "Select Circle", "Default to Select Circle"),
            ('builtin.select_lasso', "Select Lasso", "Default to Select Lasso"),
            ('builtin.select', "Tweak", "Default to Tweak"),
        ],
        default='builtin.select_box'
    )

    def draw(self, context):
        layout = self.layout
        
        layout.label(text="Default Startup Tool:")
        layout.prop(self, "default_tool", text="")
        
        layout.separator()

        layout.label(text="Active Selection Tools in Cycle (Shortcut: W):")
        box = layout.box()
        box.prop(self, "use_tweak")
        box.prop(self, "use_select_box")
        box.prop(self, "use_select_circle")
        box.prop(self, "use_select_lasso")


# 2. Cycle Operator
class VIEW3D_OT_cycle_selection_tools(bpy.types.Operator):
    """Cycle through selected selection tools"""
    bl_idname = "view3d.cycle_selection_tools"
    bl_label = "Cycle Selection Tools"
    bl_options = {'REGISTER'}

    def execute(self, context):
        prefs = context.preferences.addons[__name__].preferences

        tool_mapping = [
            ('builtin.select', prefs.use_tweak),
            ('builtin.select_box', prefs.use_select_box),
            ('builtin.select_circle', prefs.use_select_circle),
            ('builtin.select_lasso', prefs.use_select_lasso),
        ]

        cycle_tools = [tool_id for tool_id, is_active in tool_mapping if is_active]

        if not cycle_tools:
            print("[Selection Cycle Debug] Execution cancelled: No tools enabled in preferences.")
            self.report({'WARNING'}, "No selection tools enabled in Addon Preferences")
            return {'CANCELLED'}

        current_tool = ToolSelectPanelHelper.tool_active_from_context(context)
        current_id = current_tool.idname if current_tool else None

        try:
            current_index = cycle_tools.index(current_id)
            next_index = (current_index + 1) % len(cycle_tools)
        except ValueError:
            next_index = 0

        target_tool = cycle_tools[next_index]
        print(f"[Selection Cycle Debug] Cycling from '{current_id}' to '{target_tool}'")

        try:
            bpy.ops.wm.tool_set_by_id(name=target_tool)
        except RuntimeError as e:
            print(f"[Selection Cycle Debug] RuntimeError on cycle execution: {e}")
            self.report({'WARNING'}, "Tool unavailable in this context")
            return {'CANCELLED'}

        return {'FINISHED'}


# 3. Startup Handler with Context Override
@persistent
def set_default_tool_on_load(dummy=None):
    addon_entry = bpy.context.preferences.addons.get(__name__)
    if not addon_entry:
        print("[Selection Cycle Debug] Addon preferences not found during file load.")
        return

    target_tool = addon_entry.preferences.default_tool
    print(f"[Selection Cycle Debug] Startup handler triggered. Target tool: '{target_tool}'")

    for window in bpy.context.window_manager.windows:
        for area in window.screen.areas:
            if area.type == 'VIEW_3D':
                for space in area.spaces:
                    if space.type == 'VIEW_3D':
                        try:
                            with bpy.context.temp_override(window=window, area=area, space_data=space):
                                bpy.ops.wm.tool_set_by_id(name=target_tool)
                            print(f"[Selection Cycle Debug] Successfully set default tool to '{target_tool}' in VIEW_3D.")
                            return
                        except Exception as e:
                            print(f"[Selection Cycle Debug] Failed setting tool context: {e}")


# 4. Keymap Setup
def add_keymap():
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if not kc:
        return

    km = kc.keymaps.get('3D View')
    if not km:
        km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')

    kmi = km.keymap_items.new(
        VIEW3D_OT_cycle_selection_tools.bl_idname,
        'W', 'PRESS', shift=False
    )
    print("[Selection Cycle Debug] Keymap 'W' registered for 3D View.")

def remove_keymap():
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if not kc:
        return

    km = kc.keymaps.get('3D View')
    if km:
        for kmi in km.keymap_items:
            if kmi.idname == VIEW3D_OT_cycle_selection_tools.bl_idname:
                km.keymap_items.remove(kmi)
                print("[Selection Cycle Debug] Keymap 'W' unregistered.")
                break


# 5. Registration
classes = (
    SELECTION_CYCLE_OT_preferences,
    VIEW3D_OT_cycle_selection_tools,
)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    add_keymap()

    if set_default_tool_on_load not in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.append(set_default_tool_on_load)
    
    print("[Selection Cycle Debug] Addon registered successfully.")

def unregister():
    if set_default_tool_on_load in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.remove(set_default_tool_on_load)

    remove_keymap()
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)
        
    print("[Selection Cycle Debug] Addon unregistered successfully.")

if __name__ == "__main__":
    register()