from pythonosc.dispatcher import Dispatcher
from pythonosc.osc_server import BlockingOSCUDPServer
from datetime import datetime
import pyautogui
import time
import sys

HOST = "127.0.0.1"
PORT = 9001
PARAMETER = "/avatar/parameters/DiscordSend"

# Discordの初期状態を「ミュート中」と仮定
discord_muted = True
button_pressed = False
last_action_time = 0.0
DEBOUNCE_SECONDS = 0.3

def log(level, message):
    now = datetime.now().strftime("%H:%M:%S")
    print(f"[{level}] {now} {message}", flush=True)

def wait_exit():
    input("Press Enter to exit...")

def press_discord_mute_hotkey():
    pyautogui.hotkey("ctrl", "shift", "m")

def handle_discord_send(address, *args):
    global discord_muted
    global button_pressed
    global last_action_time

    if not args:
        log("ERROR", "OSC args is empty")
        return

    value = args[0]
    now_ts = time.time()

    if isinstance(value, bool):
        is_pressed = value
    elif isinstance(value, int) or isinstance(value, float):
        is_pressed = value != 0
    else:
        log("ERROR", f"unsupported value type value={value}")
        return

    if now_ts - last_action_time < DEBOUNCE_SECONDS:
        return

    # 押した瞬間: ミュート解除
    if is_pressed and not button_pressed:
        button_pressed = True

        if discord_muted:
            log("ACTION", "VRChat button pressed -> Discord unmute hotkey")
            press_discord_mute_hotkey()
            discord_muted = False
            last_action_time = now_ts
        else:
            log("INFO", "already unmuted")

        return

    # 離した瞬間: ミュート
    if not is_pressed and button_pressed:
        button_pressed = False

        if not discord_muted:
            log("ACTION", "VRChat button released -> Discord mute hotkey")
            press_discord_mute_hotkey()
            discord_muted = True
            last_action_time = now_ts
        else:
            log("INFO", "already muted")

        return

def main():
    log("CHECK", "STEP=1 OSC受信状態確認")
    log("INFO", f"host={HOST}")
    log("INFO", f"port={PORT}")
    log("INFO", f"parameter={PARAMETER}")

    log("CHECK", "STEP=2 想定状態判定")
    log("INFO", "Windows PowerShellで実行していること")
    log("INFO", "VRChat OSC Enabledであること")
    log("INFO", "Discordのミュート切替キーが Ctrl+Shift+M であること")
    log("INFO", "Discordの現在状態はミュート中として扱います")

    answer = input("[ACTION] 続行しますか？ yes/no: ").strip().lower()

    if answer != "yes":
        if answer == "no":
            log("FATAL", "ユーザー操作により停止 STEP=2")
            wait_exit()
            sys.exit(1)

        log("ERROR", "不正入力です STEP=2")
        wait_exit()
        sys.exit(1)

    log("ACTION", "STEP=3 OSC受信開始")
    log("INFO", "VRChatのメニューを押している間だけDiscordミュート解除します")
    log("INFO", "停止する場合は Ctrl+C")

    dispatcher = Dispatcher()
    dispatcher.map(PARAMETER, handle_discord_send)

    try:
        server = BlockingOSCUDPServer((HOST, PORT), dispatcher)
        server.serve_forever()
    except KeyboardInterrupt:
        log("INFO", "Ctrl+C detected")
    except Exception as e:
        log("FATAL", f"OSC server error STEP=3 detail={e}")
        wait_exit()
        sys.exit(1)

    log("CHECK", "STEP=4 結果確認")
    log("INFO", "終了しました")

if __name__ == "__main__":
    main()
