"""Provide functionality to record stream."""
import threading
from typing import List

from homeassistant.core import callback

from .core import Segment, StreamOutput, PROVIDERS


@callback
def async_setup_recorder(hass):
    """Only here so Provider Registry works."""


def recorder_save_worker(file_out: str, segments: List[Segment]):
    """Handle saving stream."""
    import av

    output = av.open(file_out, "w", options={"movflags": "frag_keyframe"})
    output_v = None

    for segment in segments:
        # Seek to beginning and open segment
        segment.segment.seek(0)
        source = av.open(segment.segment, "r", format="mpegts")
        source_v = source.streams.video[0]

        # Add output streams
        if not output_v:
            output_v = output.add_stream(template=source_v)

        # Remux video
        for packet in source.demux(source_v):
            if packet is not None and packet.dts is not None:
                packet.stream = output_v
                output.mux(packet)

    output.close()


@PROVIDERS.register("recorder")
class RecorderOutput(StreamOutput):
    """Represents HLS Output formats."""

    def __init__(self, stream, timeout: int = 30) -> None:
        """Initialize recorder output."""
        super().__init__(stream, timeout)
        self.video_path = None
        self._segments = []

    @property
    def name(self) -> str:
        """Return provider name."""
        return "recorder"

    @property
    def format(self) -> str:
        """Return container format."""
        return "mpegts"

    @property
    def audio_codec(self) -> str:
        """Return desired audio codec."""
        return "aac"

    @property
    def video_codec(self) -> str:
        """Return desired video codec."""
        return "h264"

    def prepend(self, segments: List[Segment]) -> None:
        """Prepend segments to existing list."""
        own_segments = self.segments
        segments = [s for s in segments if s.sequence not in own_segments]
        self._segments = segments + self._segments

    @callback
    def _timeout(self, _now=None):
        """Handle recorder timeout."""
        self._unsub = None
        self.cleanup()

    def cleanup(self):
        """Write recording and clean up."""
        thread = threading.Thread(
            name="recorder_save_worker",
            target=recorder_save_worker,
            args=(self.video_path, self._segments),
        )
        thread.start()

        self._segments = []
        self._stream.remove_provider(self)
