# Copyright (c) 2025, Yutang Li, SIAT (yt.li2@siat.ac.cn)
# SPDX-License-Identifier: BSD-3-Clause

"""Sim-to-VR H264 stereo streaming manager."""

import logging

logger = logging.getLogger(__name__)


class StreamingManager:
    """Manages stereo camera → H264 → TCP streaming to VR headset.

    Wraps SimVideoStreamer with graceful error handling and auto-disable on failure.
    """

    def __init__(self, host: str, port: int, scene, bitrate: int = 20_000_000):
        self._streamer = None
        self._enabled = False

        if "vr_left_eye" not in scene.sensors:
            logger.warning("[Stream] vr_left_eye camera not found. Streaming disabled.")
            return

        try:
            from mindbot.utils.sim_video_streamer import SimVideoStreamer
            cam = scene["vr_left_eye"]
            self._streamer = SimVideoStreamer(
                host=host, port=port,
                width=cam.cfg.width, height=cam.cfg.height,
                fps=30, bitrate=bitrate,
            )
            if self._streamer.connect():
                self._enabled = True
                print(f"[INFO] Sim stereo streaming to {host}:{port} "
                      f"({cam.cfg.width * 2}x{cam.cfg.height} SBS @ 30fps)")
            else:
                logger.error("[Stream] Failed to connect. Streaming disabled.")
                self._streamer = None
        except ImportError:
            logger.error("[Stream] mindbot.utils.sim_video_streamer not found. pip install av?")
        except Exception as e:
            logger.error(f"[Stream] Init failed: {e}")

    @property
    def enabled(self) -> bool:
        return self._enabled

    _debug_saved = False

    def send(self, scene, frame_count: int = 0) -> None:
        """Send one stereo frame from scene cameras. Auto-disables on failure."""
        if not self._enabled:
            return
        try:
            left_rgb = scene["vr_left_eye"].data.output["rgb"][0].cpu().numpy()
            right_rgb = scene["vr_right_eye"].data.output["rgb"][0].cpu().numpy()

            # Save debug images once (frame 5 to ensure rendering is stable)
            if frame_count == 150 and not self._debug_saved:
                self._debug_saved = True
                try:
                    from PIL import Image
                    import numpy as np
                    Image.fromarray(left_rgb[..., :3]).save("/tmp/vr_left_debug.png")
                    Image.fromarray(right_rgb[..., :3]).save("/tmp/vr_right_debug.png")
                    sbs = np.concatenate([left_rgb, right_rgb], axis=1)
                    Image.fromarray(sbs[..., :3]).save("/tmp/vr_sbs_debug.png")
                    print(f"[STREAM DIAG] Saved debug frames: left={left_rgb.shape}, right={right_rgb.shape}")
                except Exception as e:
                    print(f"[STREAM DIAG] Save failed: {e}")

            if not self._streamer.send_frame(left_rgb, right_rgb):
                logger.warning("[Stream] Connection lost. Disabling streaming.")
                self._enabled = False
        except Exception as e:
            if frame_count % 300 == 0:
                logger.warning(f"[Stream] Frame error: {e}")

    def close(self):
        if self._streamer is not None:
            self._streamer.close()
