import datetime # datetime functions
import time # time functions
# Init the keyboard listener
def Init(inGSettings):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Technical defs
import pdb
SpecialKeyList = []
inList = [
    # {
    #   "EventStartDatetime": datetime.datetime.now(),
    #   "EventEndDatetime": datetime.datetime.now(),
    #   "EventTypeStr": "MOVE", # MOVE | CLICK | SCROLL | SELECT
    #   "ValueInt": "" # MOVE: point count
    # }
]
gMoveWaitNextPointSecondsMaxFloat = 5
gMoveWaitNextPointPercentFloat = 4
gMoveWaitNextPointSecondsFloat = None
gMovePrevious = None # {"EventDatetime": datetime.datetime.now(), "XInt": None, "YInt": None}
gMovePointCountInt = None
gMoveFirstDatetime = None
gMoveCloseCheckIntervalSecondsFloat = 3

from pynput import mouse
import mouse as mouse_new # https://github.com/boppreh/mouse#mouse.hook
def on_move(x, y):
    global gMovePrevious
    global gMoveWaitNextPointSecondsFloat
    global gMoveWaitNextPointPercentFloat
    global gMovePointCountInt
    global gMoveFirstDatetime
    lNowDatetime = datetime.datetime.now()
    if gMovePrevious is None:
        gMoveFirstDatetime = lNowDatetime
        gMovePrevious = {"EventDatetime": gMoveFirstDatetime, "XInt": x, "YInt": y}
        gMovePointCountInt = 1
    else:
        lMovePreviousNew = {"EventDatetime": lNowDatetime, "XInt": x, "YInt": y}
        lNewOldDeltaSecondsFloat = (lMovePreviousNew["EventDatetime"]-gMovePrevious["EventDatetime"]).total_seconds()
        if gMoveWaitNextPointSecondsFloat is None: # We have no wait time - just calculate it
            gMoveWaitNextPointSecondsFloat = lNewOldDeltaSecondsFloat * gMoveWaitNextPointPercentFloat  # in the end for the next point
            gMovePrevious = {"EventDatetime": lNowDatetime, "XInt": x, "YInt": y}
            gMovePointCountInt = gMovePointCountInt + 1
        else: # check if we apply in time - else create new move record
            if gMoveWaitNextPointSecondsFloat >= lNewOldDeltaSecondsFloat: # In applied second wait range
                # Rewrite the globals
                gMoveWaitNextPointSecondsFloat = lNewOldDeltaSecondsFloat * gMoveWaitNextPointPercentFloat  # in the end for the next point
                gMovePrevious = {"EventDatetime": lNowDatetime, "XInt": x, "YInt": y}
                gMovePointCountInt = gMovePointCountInt + 1
            else:
                if "left" not in SpecialKeyList:
                    pass
                    # Add in result list
                    #lResult = {
                    #   "EventStartDatetime": gMoveFirstDatetime,
                    #   "EventEndDatetime": lNowDatetime,
                    #   "EventTypeStr": "MOVE", # MOVE | CLICK | SCROLL | SELECT
                    #   "ValueInt": gMovePointCountInt # MOVE: point count
                    #}
                    #inList.append(lResult)
                    #print(lResult)
                    ## Close the move
                    #gMoveWaitNextPointSecondsFloat = None
                    #gMovePrevious = None
                    #gMovePointCountInt = None
                    #gMoveFirstDatetime= None
    #print('Pointer moved to {0}'.format(
    #    (x, y)))

def on_click(inButtonEvent):
    global SpecialKeyList
    global gMovePrevious
    global gMoveWaitNextPointSecondsFloat
    global gMoveWaitNextPointPercentFloat
    global gMovePointCountInt
    global gMoveFirstDatetime
    lNowDatetime = datetime.datetime.now()
    if inButtonEvent.button=="left" and inButtonEvent.event_type == "down":
        SpecialKeyList.append("left")
        # Close the previous move action
        if gMovePrevious is not None:
            # Add in result list
            lResult = {
                "EventStartDatetime": gMoveFirstDatetime,
                "EventEndDatetime": lNowDatetime,
                "EventTypeStr": "MOVE",  # MOVE | CLICK | SCROLL | SELECT
                "ValueInt": gMovePointCountInt  # MOVE: point count
            }
            inList.append(lResult)
            print(lResult)
            # Close the move
            gMoveWaitNextPointSecondsFloat = None
            gMovePrevious = None
            gMovePointCountInt = None
            gMoveFirstDatetime = None
    elif inButtonEvent.button=="left" and inButtonEvent.event_type == "up":
        if "left" in SpecialKeyList: SpecialKeyList.remove("left")
        # Close the previous move action
        if gMovePrevious is not None:
            # Add in result list
            lResult = {
                "EventStartDatetime": gMoveFirstDatetime,
                "EventEndDatetime": lNowDatetime,
                "EventTypeStr": "SELECT",  # MOVE | CLICK | SCROLL | SELECT
                "ValueInt": gMovePointCountInt  # MOVE: point count
            }
            inList.append(lResult)
            print(lResult)
            # Close the move
            gMoveWaitNextPointSecondsFloat = None
            gMovePrevious = None
            gMovePointCountInt = None
            gMoveFirstDatetime = None
        else:
            # Add in result list
            lResult = {
                "EventStartDatetime": lNowDatetime,
                "EventEndDatetime": lNowDatetime,
                "EventTypeStr": "CLICK",  # MOVE | CLICK | SCROLL | SELECT
                "ValueInt": 'left'  # MOVE: point count
            }
            inList.append(lResult)
            print(lResult)
            # Close the move
            gMoveWaitNextPointSecondsFloat = None
            gMovePrevious = None
            gMovePointCountInt = None
            gMoveFirstDatetime = None
    elif inButtonEvent.button=="right" and inButtonEvent.event_type == "up":
        # Add in result list
        lResult = {
            "EventStartDatetime": lNowDatetime,
            "EventEndDatetime": lNowDatetime,
            "EventTypeStr": "CLICK",  # MOVE | CLICK | SCROLL | SELECT
            "ValueInt": 'right'  # MOVE: point count
        }
        inList.append(lResult)
        print(lResult)
    elif inButtonEvent.button=="middle" and inButtonEvent.event_type == "up":
        # Add in result list
        lResult = {
            "EventStartDatetime": lNowDatetime,
            "EventEndDatetime": lNowDatetime,
            "EventTypeStr": "CLICK",  # MOVE | CLICK | SCROLL | SELECT
            "ValueInt": 'middle'  # MOVE: point count
        }
        inList.append(lResult)
        print(lResult)

def on_scroll(x, y, dx, dy):
    print('Scrolled {0} at {1}'.format(
        'down' if dy < 0 else 'up',
        (x, y)))

# Collect events until released
#with mouse.Listener(
#        on_move=on_move,
#        on_click=on_click,
#        on_scroll=on_scroll) as listener:
#    listener.join()

# ...or, in a non-blocking fashion:
#listener = mouse.Listener(
#    on_move=on_move,
#    on_click=on_click,
#    on_scroll=on_scroll)
#listener.start()
def Test(inArg):
    if type(inArg) is mouse_new._mouse_event.MoveEvent:
        on_move(x = inArg.x, y = inArg.y)
    elif type(inArg) is mouse_new._mouse_event.ButtonEvent:
        on_click(inButtonEvent = inArg)
    elif type(inArg) is mouse_new._mouse_event.WheelEvent:
        print(inArg)
mouse_new.hook(Test)

import pprint
while True:
    # Check move interval
    lNowDatetime = datetime.datetime.now()
    if gMovePrevious is not None and gMoveWaitNextPointSecondsMaxFloat is not None and "left" not in SpecialKeyList:
        lNewOldDeltaSecondsFloat = (lNowDatetime - gMovePrevious["EventDatetime"]).total_seconds()
        if lNewOldDeltaSecondsFloat > gMoveWaitNextPointSecondsMaxFloat:
            # Add in result list
            lResult = {
                "EventStartDatetime": gMoveFirstDatetime,
                "EventEndDatetime": lNowDatetime,
                "EventTypeStr": "MOVE",  # MOVE | CLICK | SCROLL | SELECT
                "ValueInt": gMovePointCountInt  # MOVE: point count
            }
            inList.append(lResult)
            print(lResult)
            # Close the move
            gMoveWaitNextPointSecondsFloat = None
            gMovePrevious = None
            gMovePointCountInt = None
            gMoveFirstDatetime = None
    time.sleep(gMoveCloseCheckIntervalSecondsFloat)
    #print(inList)
    #pprint.pprint(inList)