"""
[단계 6] ESP32-CAM 영상 수신과 화면 표시 + 색공간 변환

학습 목표:
  - cv2.VideoCapture로 MJPEG 스트림 읽기
  - 영상 좌우 미러링 (cv2.flip)
  - BGR ↔ HSV 변환

조작:
  q : 종료
  v : 보기 모드 전환 (원본 / HSV / 4분할)

⚠️ 주의
  - ESP32-CAM 펌웨어는 동시에 1개 클라이언트만 지원합니다.
  - 브라우저에서 스트림을 보고 있다면 먼저 닫으세요.
"""

import cv2
import numpy as np

# ──────────────────────────────────────────
# 설정
# ──────────────────────────────────────────

# TODO 1: ESP32_IP를 본인 차량 IP로 변경
ESP32_IP = "192.168.137.74"
STREAM_URL = f"http://{ESP32_IP}:80/stream"


# ──────────────────────────────────────────
# 함수
# ──────────────────────────────────────────

def make_4panel(frame_bgr):
    """원본 + HSV 3채널 4분할 영상을 만든다."""
    hsv = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2HSV)

    # TODO 2: hsv를 H, S, V 세 채널로 분리
    # 힌트: cv2.split(hsv) 사용
    h, s, v = None, None, None  # 이 줄을 수정하세요

    # 1채널 흑백을 3채널 BGR로 변환 (붙이기 위해)
    h_bgr = cv2.cvtColor(h, cv2.COLOR_GRAY2BGR)
    s_bgr = cv2.cvtColor(s, cv2.COLOR_GRAY2BGR)
    v_bgr = cv2.cvtColor(v, cv2.COLOR_GRAY2BGR)

    # 라벨 붙이기
    cv2.putText(frame_bgr, "BGR", (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
    cv2.putText(h_bgr, "H",       (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
    cv2.putText(s_bgr, "S",       (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
    cv2.putText(v_bgr, "V",       (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)

    top    = np.hstack([frame_bgr, h_bgr])
    bottom = np.hstack([s_bgr,     v_bgr])
    return np.vstack([top, bottom])


# ──────────────────────────────────────────
# 메인
# ──────────────────────────────────────────

def main():
    print(f"스트림 연결: {STREAM_URL}")
    cap = cv2.VideoCapture(STREAM_URL)

    if not cap.isOpened():
        print("스트림 연결 실패! 다음을 확인하세요:")
        print("  1) ESP32_IP가 맞는가?")
        print("  2) 같은 Wi-Fi에 연결되어 있는가?")
        print("  3) 브라우저가 스트림을 점유하고 있지 않은가?")
        return

    mode = 'original'  # 'original' / 'hsv' / '4panel'

    while True:
        ret, frame = cap.read()
        if not ret:
            print("프레임 수신 실패")
            continue

        # TODO 3: frame을 좌우 반전 (카메라 미러링 보정)
        # 힌트: cv2.flip(frame, 1)
        # frame = ...

        # 보기 모드별 표시
        if mode == 'original':
            display = frame
        elif mode == 'hsv':
            display = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        elif mode == '4panel':
            display = make_4panel(frame.copy())
        else:
            display = frame

        cv2.imshow('ESP32-CAM', display)

        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            break
        elif key == ord('v'):
            # 모드 순환
            modes = ['original', 'hsv', '4panel']
            idx = modes.index(mode)
            mode = modes[(idx + 1) % len(modes)]
            print(f"모드: {mode}")

    cap.release()
    cv2.destroyAllWindows()
    print("종료")


if __name__ == "__main__":
    main()


# ════════════════════════════════════════════════════════════
# 정답
# ════════════════════════════════════════════════════════════
"""
[TODO 2] h, s, v = cv2.split(hsv)
[TODO 3] frame = cv2.flip(frame, 1)
"""
