import platform
import threading

def check_os():
    os_name = platform.system()
    if os_name == "Darwin":
        return "macOS"
    elif os_name == "Windows":
        return "Windows"
    elif os_name == "Linux":
        return "Linux"
    else:
        print(f"Unknown operating system: {os_name}")

os = check_os()

if os == "macOS":
    from Quartz import CGEventTapCreate, kCGEventKeyDown, kCGHeadInsertEventTap, kCGEventTapOptionDefault
    from Quartz import CGEventMaskBit, CGEventTapEnable, CGEventTapIsEnabled
    from Quartz import CFRunLoopGetCurrent, CFRunLoopAddSource, CFRunLoopRun
    from Quartz import CFMachPortCreateRunLoopSource
    from Quartz import kCFRunLoopCommonModes
    import Quartz

    key_map = {
        0: "a", 1: "s", 2: "d", 3: "f", 4: "h", 5: "g", 6: "z", 7: "x", 8: "c", 9: "v",
        10: "`", 11: "b", 12: "q", 13: "w", 14: "e", 15: "r", 16: "y", 17: "t", 18: "1", 19: "2",
        20: "3", 21: "4", 22: "6", 23: "5", 24: "=", 25: "9", 26: "7", 27: "-", 28: "8", 29: "0",
        30: "]", 31: "o", 32: "u", 33: "[", 34: "i", 35: "p", 36: "enter", 37: "l", 38: "j", 39: "'",
        40: "k", 41: ";", 42: "\\", 43: ",", 44: "/", 45: "n", 46: "m", 47: ".", 48: "tab", 49: "space",
        50: "`", 51: "backspace", 52: "enter", 53: "esc", 54: "cmd", 55: "cmd", 56: "shift", 57: "caps lock",
        58: "alt", 59: "ctrl", 60: "shift", 61: "alt", 62: "ctrl", 63: "fn",
        64: "f17", 65: "kp_decimal", 66: "f13", 67: "kp_enter", 68: "f14", 69: "kp_equal", 70: "f15",
        71: "f16", 72: "kp_0", 73: "kp_1", 74: "kp_2", 75: "kp_3", 76: "kp_4", 77: "kp_5",
        78: "kp_6", 79: "kp_7", 80: "f18", 81: "kp_8", 82: "kp_9", 83: "f19",
        84: "f20", 85: "kp_divide", 86: "kp_multiply", 87: "kp_subtract", 88: "kp_add", 89: "f5",
        90: "f6", 91: "f7", 92: "f3", 93: "f8", 94: "f9", 95: "f11", 96: "f13",
        97: "f16", 98: "f14", 99: "f10", 100: "f12", 101: "f15", 102: "insert",
        103: "home", 104: "page up", 105: "delete", 106: "f4", 107: "end", 108: "f2",
        109: "page down", 110: "f1", 111: "left", 112: "right", 113: "down", 114: "up"
    }

    class MacOSKeylogger:
        def __init__(self):
            self.keycode = None
            self.startListening()

        def keycode_to_char(self, keycode):
            return key_map.get(keycode, f"UNKNOWN_KEYCODE_{keycode}")

        # Fonction de callback pour intercepter les touches
        def keyboard_callback(self, proxy, event_type, event, refcon):
            if event_type == kCGEventKeyDown:
                self.keycode = Quartz.CGEventGetIntegerValueField(event, Quartz.kCGKeyboardEventKeycode)
                #print(f"Touche pressée : {self.keycode_to_char(self.keycode)} ({self.keycode})")  # Affichage du keycode
            return event

        def start_keylogger(self):
            # Création de l'event tap
            event_mask = CGEventMaskBit(kCGEventKeyDown)
            event_tap = CGEventTapCreate(
                Quartz.kCGSessionEventTap,
                kCGHeadInsertEventTap,
                kCGEventTapOptionDefault,
                event_mask,
                self.keyboard_callback,
                None
            )

            if event_tap:
                run_loop_source = CFMachPortCreateRunLoopSource(None, event_tap, 0)
                CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes)

                CGEventTapEnable(event_tap, True)# Activation du Tap

                #print("Écoute des touches du clavier...")
                CFRunLoopRun() # Lancer la boucle d'événements
            else:
                print("Erreur : Impossible de créer l'event tap. Vérifie les permissions.")

        def getKey(self):
            return self.keycode_to_char(self.keycode)
        
        def startListening(self):
            keylogger_thread = threading.Thread(target=self.start_keylogger, daemon=True)
            keylogger_thread.start()


if os == "Windows" or os == "Linux":
    import keyboard

    class WindowsKeylogger:
        def __init__(self):
            self.keycode = None
            self.startListening()

        def getKey(self):
            return self.keycode

        def startListening(self):
            keyboard.on_press(self.onKeyPress)

        def onKeyPress(self, event):
            self.keycode = event.name

class KeyBordCrossPlatform:
    def __init__(self):
        self.os = check_os()
        if os == "macOS":
            self.keylogger = MacOSKeylogger()
        elif os == "Windows":
            self.keylogger = WindowsKeylogger()
        else:
            raise Exception("OS not supported")

    def getKey(self):
        return self.keylogger.getKey()
    

"""
EXEMPLE D'UTILISATION
"""
if __name__ == "__main__":
    keylogger = KeyBordCrossPlatform()
    
    while True:
        if keylogger.getKey() == "esc":
            break
