#!/usr/bin/env python3
"""
gamepad_check.py — ゲーム用コントローラーの入力を読んで表示するだけの確認スクリプト

ロボットには一切つながない。ファイルにも何も書き込まない。

使い方（Mac）:
    python3 -m pip install pygame
    python3 gamepad_check.py

見ること:
    1. ボタンを押す・離すと、番号と押した/離したが出るか
    2. スティックを倒すと、軸の値が -1.0〜+1.0 の間で動くか
    3. スティックを離したとき、値が 0 付近に戻るか（終了時の一覧で「最後の値」を見る）

終了: ウィンドウを閉じる、または ESC キー、またはターミナルで Ctrl+C
"""

import os
import sys
import time

# ウィンドウが手前にないときもコントローラーの入力を受け取る
os.environ.setdefault("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "1")

import pygame  # noqa: E402

AXIS_PRINT_STEP = 0.05   # 軸の値がこれ以上変わったらターミナルに出す
WINDOW_SIZE = (560, 420)


def describe(js):
    return (f"[{js.get_instance_id()}] {js.get_name()}  "
            f"軸={js.get_numaxes()}  ボタン={js.get_numbuttons()}  "
            f"十字キー={js.get_numhats()}  GUID={js.get_guid()}")


def main():
    pygame.init()
    pygame.joystick.init()
    screen = pygame.display.set_mode(WINDOW_SIZE)
    pygame.display.set_caption("gamepad_check")
    # ウィンドウの文字は英数字だけにする（日本語フォントがなくても化けないように）
    font = pygame.font.SysFont("menlo,consolas,dejavusansmono", 16)
    clock = pygame.time.Clock()

    sticks = {}          # instance_id -> Joystick
    last_axis = {}       # (id, axis) -> 最後に表示した値
    axis_stats = {}      # (id, axis) -> [最小, 最大, 最後の値]
    t0 = time.monotonic()

    def ts():
        return f"{time.monotonic() - t0:8.3f}s"

    print("コントローラーを待っています（つないでいなければ、今つないでください）")

    running = True
    try:
        while running:
            for ev in pygame.event.get():
                if ev.type == pygame.QUIT:
                    running = False
                elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE:
                    running = False

                elif ev.type == pygame.JOYDEVICEADDED:
                    js = pygame.joystick.Joystick(ev.device_index)
                    sticks[js.get_instance_id()] = js
                    print(f"{ts()}  接続: {describe(js)}")
                elif ev.type == pygame.JOYDEVICEREMOVED:
                    js = sticks.pop(ev.instance_id, None)
                    name = js.get_name() if js else "?"
                    print(f"{ts()}  切断: [{ev.instance_id}] {name}")

                elif ev.type == pygame.JOYBUTTONDOWN:
                    print(f"{ts()}  ボタン {ev.button:2d}  押した")
                elif ev.type == pygame.JOYBUTTONUP:
                    print(f"{ts()}  ボタン {ev.button:2d}  離した")

                elif ev.type == pygame.JOYHATMOTION:
                    print(f"{ts()}  十字キー {ev.hat}  {ev.value}")

                elif ev.type == pygame.JOYAXISMOTION:
                    key = (ev.instance_id, ev.axis)
                    v = ev.value
                    st = axis_stats.setdefault(key, [v, v, v])
                    st[0] = min(st[0], v)
                    st[1] = max(st[1], v)
                    st[2] = v
                    prev = last_axis.get(key)
                    if prev is None or abs(v - prev) >= AXIS_PRINT_STEP:
                        last_axis[key] = v
                        print(f"{ts()}  軸 {ev.axis}  {v:+.3f}")

            # ウィンドウに今の値を並べる
            screen.fill((20, 20, 24))
            y = 10
            if not sticks:
                screen.blit(font.render("no controller", True, (230, 180, 80)), (10, y))
            for js in sticks.values():
                screen.blit(font.render(js.get_name()[:50], True, (200, 220, 255)), (10, y))
                y += 24
                for a in range(js.get_numaxes()):
                    v = js.get_axis(a)
                    screen.blit(font.render(f"axis {a}: {v:+.3f}", True, (230, 230, 230)), (10, y))
                    # 値の棒（中央が0）
                    cx, w = 200, 150
                    pygame.draw.rect(screen, (70, 70, 80), (cx - w, y + 4, 2 * w, 10), 1)
                    pygame.draw.rect(screen, (90, 200, 120), (cx, y + 4, int(v * w), 10) if v >= 0
                                     else (cx + int(v * w), y + 4, int(-v * w), 10))
                    y += 20
                pressed = [str(b) for b in range(js.get_numbuttons()) if js.get_button(b)]
                screen.blit(font.render("buttons: " + (" ".join(pressed) or "-"),
                                        True, (230, 230, 230)), (10, y))
                y += 20
                for h in range(js.get_numhats()):
                    screen.blit(font.render(f"hat {h}: {js.get_hat(h)}", True, (230, 230, 230)), (10, y))
                    y += 20
                y += 10
            pygame.display.flip()
            clock.tick(60)
    except KeyboardInterrupt:
        pass
    finally:
        if axis_stats:
            print("\n--- 軸の一覧（スティックを離した状態で終えると、最後の値＝戻り位置） ---")
            for (iid, axis), (lo, hi, last) in sorted(axis_stats.items()):
                print(f"[{iid}] 軸 {axis}:  最小 {lo:+.3f}  最大 {hi:+.3f}  最後の値 {last:+.3f}")
        pygame.quit()


if __name__ == "__main__":
    sys.exit(main())
