 # -*- coding:UTF-8 -*-

import RPi.GPIO as GPIO
import threading
import time
import numpy as np

class RaKeypad:


    _keys = list()
    _funcKeyUp = list()
    _funcKeyDown = list()
    _funcKeyPress = list()
    _funcKeyHold = list()

    def __init__(self, Components, pins):
        """
        Initialisiert das RaKeypad

        :param Components: RaComponents Element
        :type Components: RaComponents

        :param Pins: Die Pin-Belegung für das Keypad
        :type Pins: list
        """
        self.components = Components
        self.__enabled = True
        self.pins = pins
        self.__init_gpio()
        self.lock = threading.Lock()
        self.keyThread = threading.Thread(target=self.__threadRaKeypad)
        self.keyThread.start()

    def Enabled(self, value=None):
        if value!=None:
            if isinstance(value, bool):
                self.__enabled = value
            elif isinstance(value, int):
                if value>0:
                    self.__enabled = True
                else:
                    self.__enabled = False
            elif isinstance(value, str):
                sval = value.lower()
                if sval=="n" or sval=="false" or sval=="0" or sval=="no" or sval=="disabled":
                    self.__enabled = False
                else:
                    self.__enabled = True
        return self.__enabled


    def join(self):
        """
        Erstellt einen Join zu dem Thread
        """
        self.keyThread.join()

    def __init_gpio(self):
        """
        Initialisiert die GPIO-Pins für die Buttons.
        """
        self._keys = list()
        GPIO.setmode(GPIO.BCM)
        for pin_name, pin_number in self.pins.items():
            GPIO.setup(pin_number, GPIO.IN, pull_up_down=GPIO.PUD_UP)
            self._keys.append({
                "name": pin_name,
                "pin": pin_number,
                "pressed": False,
                "duration": 0
            })

    def register(self, keyDown, keyUp, keyPress, keyHold):
        """
        Registriert Funktionen für KeyDown, KeyUp und KeyPress Events

        :keyDown: function(key)
        :keyUp: function(key)
        :keyPress: function(key, duration)
        :keyHold: function(key, duration)
        """
        self.registerKeyDown(keyDown)
        self.registerKeyUp(keyUp)
        self.registerKeyPress(keyPress)
        self.registerKeyPress(keyHold)

    def registerKeyUp(self, func):
        """
        Registriert Funktionen für KeyUp Events

        :func: function(key)
        """
        if func not in self._funcKeyUp and func is not None:
            self._funcKeyUp.append(func)

    def registerKeyDown(self, func):
        """
        Registriert Funktionen für KeyDown Events

        :func: function(key)
        """
        if func not in self._funcKeyDown and func is not None:
            self._funcKeyDown.append(func)

    def registerKeyPress(self, func):
        """
        Registriert Funktionen für KeyPress Events

        :func: function(key, duration)
        """
        if func not in self._funcKeyPress and func is not None:
            self._funcKeyPress.append(func)

    def registerKeyHold(self, func):
        """
        Registriert Funktionen für KeyHold Events

        :func: function(key, duration)
        """
        if func not in self._funcKeyHold and func is not None:
            self._funcKeyHold.append(func)

    def unregisterKeyUp(self, func):
        """
        Entfernt die Registrierung für KeyUp Events

        :func: function(key)
        """
        if func in self._funcKeyUp:
            self._funcKeyUp.remove(func)

    def unregisterKeyDown(self, func):
        """
        Entfernt die Registrierung für KeyDown Events

        :func: function(key)
        """
        if func in self._funcKeyDown:
            self._funcKeyDown.remove(func)

    def unregisterKeyPress(self, func):
        """
        Entfernt die Registrierung für KeyPress Events

        :func: function(key)
        """
        if func in self._funcKeyPress:
            self._funcKeyPress.remove(func)

    def unregisterKeyPress(self, func):
        """
        Entfernt die Registrierung für KeyPress Events

        :func: function(key)
        """
        if func in self._funcKeyHold:
            self._funcKeyHold.remove(func)

    def unregister(self, func):
        """
        Entfernt die Registrierung für Alle KeyEvents

        :func: function(key) / function(key, duration)
        """
        self.unregisterKeyUp(func)
        self.unregisterKeyDown(func)
        self.unregisterKeyPress(func)
        self.unregisterKeyHold(func)


    pressSkill = 0
    def __threadRaKeypad(self):
        keyNum = len(self._keys)
        while True:
            with self.lock:
                if self.__enabled==False:
                    time.sleep(0.8)
                else:
                    time.sleep(0.05)
                    for i in range(keyNum):
                        if GPIO.input(self._keys[i]["pin"]) == 0:
                            if self._keys[i]["pressed"]==False:
                                self.__keyDown(self._keys[i]["name"])
                                self.__keyHold(self._keys[i]["name"], 0.0)
                                self._keys[i]["duration"]=time.perf_counter()
                                self._keys[i]["pressed"]=True
                            elif time.perf_counter() - self._keys[i]["duration"]>1:
                                print("Call Hold")
                                dur = time.perf_counter() - self._keys[i]["duration"]
                                self.__keyHold(self._keys[i]["name"], dur)

                        else:
                            if self._keys[i]["pressed"]==True:
                                dur = time.perf_counter() - self._keys[i]["duration"]
                                self._keys[i]["pressed"]=False
                                self.__keyUp(self._keys[i]["name"])
                                self.__keyPress(self._keys[i]["name"], dur)
                                self._keys[i]["duration"] = 0


    def __keyPress(self, key, duration):
        for f in self._funcKeyPress:
            if f is not None:
                f(key, duration)

    def __keyDown(self, key):
        for f in self._funcKeyDown:
            if f is not None:
                f(key)

    def __keyUp(self, key):
        for f in self._funcKeyUp:
            if f is not None:
                f(key)

    def __keyHold(self, key, duration):
        for f in self._funcKeyHold:
            if f is not None:
                f(key, duration)