# Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.

"""Native streaming interface."""

import os
from typing import List

import psutil

import carb.settings

from omni.services.streaming.manager import StreamInterface


class NativeStreamInterface(StreamInterface):
    """Native streaming interface."""

    @property
    def id(self) -> str:
        return "Native"

    @property
    def menu_label(self) -> str:
        return "Native"

    @property
    def module_name(self) -> str:
        return __name__

    @property
    def stream_urls(self) -> List[str]:
        return self.local_ips

    async def is_healthy(self) -> bool:
        """
        Check if the streaming server is in a state that is considered healthy (i.e. that the streaming server listens
        for connection requests on the configured port).

        Args:
            None

        Returns:
            bool: A flag indicating whether the streaming server is in a healthy state.

        """
        # Confirm if the superclass may have already flagged the stream as being in an unhealthy state, in order to
        # potentially return early:
        is_healthy = await super().is_healthy()
        if not is_healthy:
            return is_healthy

        # Check that the host process has the expected native streaming server port in a "LISTENING" state by querying
        # its process, rather than issuing an actual request against the server:
        kit_process = psutil.Process(pid=os.getpid())
        expected_server_port = self._get_native_streaming_port_number()
        is_listening_on_expected_port = False

        for connection in kit_process.connections():
            if connection.laddr.port == expected_server_port:
                if connection.status is psutil.CONN_LISTEN:
                    is_listening_on_expected_port = True
                break

        return is_listening_on_expected_port

    def _get_native_streaming_port_number(self) -> int:
        """
        Return the port number of on which the streaming server is expected to receive connection requests.

        Args:
            None

        Returns:
            int: The port number of on which the streaming server is expected to receive connection requests.

        """
        settings = carb.settings.get_settings()
        native_server_port = settings.get_as_int("app/livestream/port")
        return native_server_port
