import bpy
from . import utils

class GPT_OT_layer_nav(bpy.types.Operator):
    bl_idname = "gp.layer_nav"
    bl_label = "GP Layer Navigator"
    bl_description = "Change active GP layer and highlight active for a moment"
    bl_options = {'REGISTER', 'INTERNAL', 'UNDO'}

    direction : bpy.props.EnumProperty(
        name='direction',
        items=(('UP', 'Up', ''),('DOWN', 'Down', ''), ('NONE', 'None', '')),
        default='UP',
        description='Direction to change layer in active GPencil stack',
        options={'SKIP_SAVE'})

    ## hardcoded values
    # interval = 0.04 # 0.1
    # limit = 1.8
    # fade_val = 0.35
    # use_fade_in = True
    # fade_in_time = 0.5

    def invoke(self, context, event):
        ## initialise vvalue from prefs
        prefs = utils.get_addon_prefs()
        if not prefs.nav_use_fade:
            if self.direction == 'DOWN':
                utils.iterate_active_layer(context.grease_pencil, -1)
                # utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'name') # gpv2

            if self.direction == 'UP':
                utils.iterate_active_layer(context.grease_pencil, 1)
            return {'FINISHED'}
        
        ## get up and down keys for use in modal
        self.up_keys = []
        self.down_keys = []
        for km in context.window_manager.keyconfigs.user.keymaps:
            for kmi in km.keymap_items:
                if kmi.idname == 'gp.layer_nav':
                    if kmi.properties.direction == 'UP':
                        self.up_keys.append(kmi.type)
                    elif kmi.properties.direction == 'DOWN':
                        self.down_keys.append(kmi.type)

        self.interval = prefs.nav_interval
        self.limit = prefs.nav_limit
        self.fade_val = prefs.nav_fade_val
        self.use_fade_in = prefs.nav_use_fade_in
        self.fade_in_time = prefs.nav_fade_in_time

        self.lapse = 0
        wm = context.window_manager
        args = (self, context)

        if context.space_data.overlay.use_gpencil_fade_layers:
            self.fade_target = context.space_data.overlay.gpencil_fade_layer
        else:
            self.fade_target = 1.0

        self.fade_start = self.limit - self.fade_in_time

        self.first = True
        self._timer = wm.event_timer_add(self.interval, window=context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def store_settings(self, context):
        self.org_use_gpencil_fade_layers = context.space_data.overlay.use_gpencil_fade_layers
        self.org_gpencil_fade_layer = context.space_data.overlay.gpencil_fade_layer
        context.space_data.overlay.use_gpencil_fade_layers = True
        context.space_data.overlay.gpencil_fade_layer = self.fade_val

    def modal(self, context, event):
        trigger = False
        if event.type in {'RIGHTMOUSE', 'ESC', 'LEFTMOUSE'}:
            self.stop_mod(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            self.lapse += self.interval
    
            if self.lapse >= self.limit:
                self.stop_mod(context)
                return {'FINISHED'}
            
            ## Fade
            if self.use_fade_in and (self.lapse > self.fade_start):
                fade = utils.transfer_value(self.lapse, self.fade_start, self.limit, self.fade_val, self.fade_target)
                # print(f'lapse {self.lapse} - fade {fade}')
                context.space_data.overlay.gpencil_fade_layer = fade

        if self.direction == 'DOWN' or ((event.type in self.down_keys) and event.value == 'PRESS'):
            _val = utils.iterate_active_layer(context.grease_pencil, -1)
            trigger = True

        if self.direction == 'UP' or ((event.type in self.up_keys) and event.value == 'PRESS'):
            _val = utils.iterate_active_layer(context.grease_pencil, 1)
            trigger = True

        if trigger:
            self.direction = 'NONE'
            if self.first:
                self.store_settings(context)
                self.first=False

            if self.use_fade_in:
                # reset fade to wanted value
                context.space_data.overlay.gpencil_fade_layer = self.fade_val

            self.lapse = 0 # reset counter
            return {'RUNNING_MODAL'}#running modal prevent original usage to be triggered (capture keys)

        return {'PASS_THROUGH'}

    def stop_mod(self, context):
        # restore fade
        context.space_data.overlay.use_gpencil_fade_layers = self.org_use_gpencil_fade_layers
        context.space_data.overlay.gpencil_fade_layer = self.org_gpencil_fade_layer
        wm = context.window_manager
        wm.event_timer_remove(self._timer)


addon_keymaps = []

def register_keymap():
    addon = bpy.context.window_manager.keyconfigs.addon

    km = addon.keymaps.new(name = "Grease Pencil Paint Mode", space_type = "EMPTY")
    
    kmi = km.keymap_items.new('gp.layer_nav', type='PAGE_UP', value='PRESS')
    kmi.properties.direction = 'UP'
    addon_keymaps.append((km, kmi))

    kmi = km.keymap_items.new('gp.layer_nav', type='PAGE_DOWN', value='PRESS')
    kmi.properties.direction = 'DOWN'
    addon_keymaps.append((km, kmi))

def unregister_keymap():
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)

    addon_keymaps.clear()

def register():
    bpy.utils.register_class(GPT_OT_layer_nav)
    register_keymap()

def unregister():
    unregister_keymap()
    bpy.utils.unregister_class(GPT_OT_layer_nav)