# GstMini
# Copyright (C) 2025 Rafael Caricio <rafael@caricio.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

from ..core.element import GstElement
from ..core.pad import GstFlowReturn
from ..core.buffer import GstBuffer, BufferFlags


class FakeSink(GstElement):
    def __init__(self, name, sync: bool = False):
        super().__init__(name)
        # properties
        self.sync = sync

        # state
        self.buffer_count = 0

        self.sink_pad = self.create_sink_pad("sink")
        self.sink_pad.set_chain_function(self._chain)

    def on_ready(self):
        self.buffer_count = 0

    def _chain(self, buffer: GstBuffer) -> GstFlowReturn:
        if buffer.has_flag(BufferFlags.EOS):
            self.log("Received EOS")
            return GstFlowReturn.EOS

        # Extract timestamp
        pts = buffer.pts

        # Convert stream time to running time (gst_segment_to_running_time)
        # Corresponds to gstbasesink.c:2207
        running_time = self.segment.to_running_time(pts)

        if running_time < 0:
            self.log("Buffer outside segment, dropping")
            return GstFlowReturn.OK

        # Synchronization (gst_base_sink_do_sync)
        if self.sync and self.state.name == 'PLAYING':
            # Calculate clock time: running_time + base_time
            # Corresponds to gstbasesink.c:2356
            clock_time = running_time + self.pipeline.base_time

            # Wait on clock (gst_base_sink_wait_clock at gstbasesink.c:2381)
            self.log(f"Waiting for clock_time={clock_time:.3f}s...")

            _, jitter = self.pipeline.clock.wait_until(clock_time)
            jitter_ms = jitter * 1000

            if jitter >= 0:
                self.log(f"Clock wait complete (jitter: {jitter_ms:+.1f}ms)")
            else:
                self.log(f"Buffer late (jitter: {jitter_ms:+.1f}ms)")

        self.buffer_count += 1
        self.log(f"Processed {repr(buffer)}")
        return GstFlowReturn.OK
