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

import av

from homeassistant.core import callback

from .const import OUTPUT_CONTAINER_FORMAT
from .core import Segment, StreamOutput

_LOGGER = logging.getLogger(__name__)


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


def recorder_save_worker(file_out: str, segments: List[Segment], container_format):
    """Handle saving stream."""
    if not os.path.exists(os.path.dirname(file_out)):
        os.makedirs(os.path.dirname(file_out), exist_ok=True)

    first_pts = {"video": None, "audio": None}
    output = av.open(file_out, "w", format=container_format)
    output_v = None
    output_a = None

    # Get first_pts values from first segment
    if len(segments) > 0:
        segment = segments[0]
        source = av.open(segment.segment, "r", format=container_format)
        source_v = source.streams.video[0]
        first_pts["video"] = source_v.start_time
        if len(source.streams.audio) > 0:
            source_a = source.streams.audio[0]
            first_pts["audio"] = int(
                source_v.start_time * source_v.time_base / source_a.time_base
            )
        source.close()

    for segment in segments:
        # Open segment
        source = av.open(segment.segment, "r", format=container_format)
        source_v = source.streams.video[0]
        # Add output streams
        if not output_v:
            output_v = output.add_stream(template=source_v)
            context = output_v.codec_context
            context.flags |= "GLOBAL_HEADER"
        if not output_a and len(source.streams.audio) > 0:
            source_a = source.streams.audio[0]
            output_a = output.add_stream(template=source_a)

        # Remux video
        for packet in source.demux():
            if packet.dts is None:
                continue
            packet.pts -= first_pts[packet.stream.type]
            packet.dts -= first_pts[packet.stream.type]
            packet.stream = output_v if packet.stream.type == "video" else output_a
            output.mux(packet)

        source.close()

    output.close()


class RecorderOutput(StreamOutput):
    """Represents HLS Output formats."""

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

    def _async_put(self, segment: Segment) -> None:
        """Store output."""
        self._segments.append(segment)

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

    def save(self):
        """Write recording and clean up."""
        _LOGGER.debug("Starting recorder worker thread")
        thread = threading.Thread(
            name="recorder_save_worker",
            target=recorder_save_worker,
            args=(self.video_path, self._segments, OUTPUT_CONTAINER_FORMAT),
        )
        thread.start()
        self._segments = []