# ===== THIS FILE IS GENERATED FROM A TEMPLATE ===== #
# ============== DO NOT EDIT DIRECTLY ============== #

from typing import Any

from ..call import call, call_async, call_sync

from ..protobufs import main_pb2


class Transport:
    """
    Connection transport backend allowing to carry Zaber ASCII protocol over arbitrary protocols.
    Can only be used with a single connection.
    """

    @property
    def transport_id(self) -> int:
        """
        The transport ID identifies this transport instance with the underlying library.
        """
        return self._transport_id

    def __init__(self, transport_id: int):
        self._transport_id = transport_id

    @staticmethod
    def open(
    ) -> 'Transport':
        """
        Creates new instance allowing to read/write messages from/to a single connection.

        Returns:
            New instance of transport.
        """
        request = main_pb2.EmptyRequest()
        response = main_pb2.CustomInterfaceOpenResponse()
        call_sync("custom/interface/open", request, response)
        return Transport(response.transport_id)

    def close(
            self
    ) -> None:
        """
        Closes the transport.
        Also closes the connection using the transport.
        """
        request = main_pb2.CustomInterfaceCloseRequest()
        request.transport_id = self.transport_id
        call("custom/interface/close", request)

    async def close_async(
            self
    ) -> None:
        """
        Closes the transport.
        Also closes the connection using the transport.
        """
        request = main_pb2.CustomInterfaceCloseRequest()
        request.transport_id = self.transport_id
        await call_async("custom/interface/close", request)

    def close_with_error(
            self,
            error_message: str
    ) -> None:
        """
        Closes the transport with error.
        Also closes the connection using the transport propagating the error.

        Args:
            error_message: Error to be propagated.
        """
        request = main_pb2.CustomInterfaceCloseRequest()
        request.transport_id = self.transport_id
        request.error_message = error_message
        call("custom/interface/close", request)

    async def close_with_error_async(
            self,
            error_message: str
    ) -> None:
        """
        Closes the transport with error.
        Also closes the connection using the transport propagating the error.

        Args:
            error_message: Error to be propagated.
        """
        request = main_pb2.CustomInterfaceCloseRequest()
        request.transport_id = self.transport_id
        request.error_message = error_message
        await call_async("custom/interface/close", request)

    def write(
            self,
            message: str
    ) -> None:
        """
        Writes a single message to the connection.
        The message will be processed as a reply from the device.

        Args:
            message: Single message of Zaber ASCII protocol.
        """
        request = main_pb2.CustomInterfaceWriteRequest()
        request.transport_id = self.transport_id
        request.message = message
        call("custom/interface/write", request)

    async def write_async(
            self,
            message: str
    ) -> None:
        """
        Writes a single message to the connection.
        The message will be processed as a reply from the device.

        Args:
            message: Single message of Zaber ASCII protocol.
        """
        request = main_pb2.CustomInterfaceWriteRequest()
        request.transport_id = self.transport_id
        request.message = message
        await call_async("custom/interface/write", request)

    def read(
            self
    ) -> str:
        """
        Reads a single message generated by the connection.
        The message is a request for the device.
        Read should be called continuously in a loop to ensure all generated messages are processed.
        Subsequent read call confirms that previous message was delivered to the device.

        Returns:
            Message generated by the connection.
        """
        request = main_pb2.CustomInterfaceReadRequest()
        request.transport_id = self.transport_id
        response = main_pb2.StringResponse()
        call("custom/interface/read", request, response)
        return response.value

    async def read_async(
            self
    ) -> str:
        """
        Reads a single message generated by the connection.
        The message is a request for the device.
        Read should be called continuously in a loop to ensure all generated messages are processed.
        Subsequent read call confirms that previous message was delivered to the device.

        Returns:
            Message generated by the connection.
        """
        request = main_pb2.CustomInterfaceReadRequest()
        request.transport_id = self.transport_id
        response = main_pb2.StringResponse()
        await call_async("custom/interface/read", request, response)
        return response.value

    def __enter__(self) -> 'Transport':
        """ __enter__ """
        return self

    def __exit__(self, _type: Any, _value: Any, _traceback: Any) -> None:
        """ __exit__ """
        self.close()
