from threading import Event, Thread

import cv2

from era_5g_client.data_sender_gstreamer import DataSenderGStreamer


# TODO should have common base with DataSenderGStreamerFromSource
class DataSenderGStreamerFromFile(Thread):
    """Class which setups gstreamer connection to the NetApp and sends the data
    from the gstreamer source."""

    def __init__(
        self,
        uri: str,
        gstreamer_port: int,
        file_name: str,
        fps: float,
        width: int,
        height: int,
        resize: bool = True,
        threads: int = 1,
        **kw,
    ) -> None:
        """Constructor.

        Args:
            uri (str): ip address or hostname of the NetApp interface
            gstreamer_port (int): the port assigned for gstreamer communication
            file_name (str): the gstreamer source, e.g. v4l2src device=/dev/video0
            fps (float): the requested FPS of the h264 stream
            width (int): the width (in pixels) the video should be resized to (if resize=True) or the
                actual width of the video (if resize=False)
            height (int): the height (in pixels) the video should be resized to (if resize=True) or the
                actual height of the video (if resize=False)
            resize (bool): indicates if the video should be resized before sending. If False,
                the width and height parameters must contain the actual resolution of the video
            threads (int, optional): the number of threads to be used to encode the h264 stream.
                Defaults to 1.
        """

        super().__init__(**kw)
        self.stop_event = Event()
        # instantiate the base data sender object
        self.data_sender_gstreamer = DataSenderGStreamer(uri, gstreamer_port, fps, width, height)

        # creates the video capture and runs the thread
        self.cap = cv2.VideoCapture(file_name)
        if not self.cap.isOpened():
            raise Exception("Cannot open video file")

        self.resize = resize

    def stop(self) -> None:
        self.stop_event.set()

    def run(self) -> None:
        """Reads the data from the gstreamer source and sends it using the base
        data sender."""

        while not self.stop_event.is_set():
            ret, frame = self.cap.read()
            if not ret:
                break
            if self.resize:
                resized = cv2.resize(
                    frame,
                    (self.data_sender_gstreamer.width, self.data_sender_gstreamer.height),
                    interpolation=cv2.INTER_AREA,
                )
                self.data_sender_gstreamer.send_image(resized)
            else:
                self.data_sender_gstreamer.send_image(frame)
        self.cap.release()
        self.data_sender_gstreamer.out.release()
