# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: SSE.proto
# plugin: python-betterproto2
# This file has been @generated

__all__ = (
    "BundledRows",
    "Capabilities",
    "CommonRequestHeader",
    "ConnectorBase",
    "ConnectorStub",
    "DataType",
    "Dual",
    "Empty",
    "FieldDescription",
    "FunctionDefinition",
    "FunctionRequestHeader",
    "FunctionType",
    "Parameter",
    "Row",
    "ScriptRequestHeader",
    "TableDescription",
)

from collections.abc import AsyncIterator, Iterable, Iterator
from dataclasses import dataclass
from typing import TYPE_CHECKING

import betterproto2
import grpc
import grpclib
from betterproto2 import grpclib as betterproto2_grpclib

from ...message_pool import default_message_pool

if TYPE_CHECKING:
    import grpclib.server

_COMPILER_VERSION = "0.9.0"
betterproto2.check_compiler_version(_COMPILER_VERSION)


class DataType(betterproto2.Enum):
    """
    *
    Data types of the parameters and return values.
    """

    STRING = 0
    """
    / Contains only string.
    """

    NUMERIC = 1
    """
    / Contains only double.
    """

    DUAL = 2
    """
    / Contains both a string and a double.
    """


class FunctionType(betterproto2.Enum):
    """
    *
    Types of functions (determined by their return values).
    """

    SCALAR = 0
    """
    / The return value is a scalar per row.
    """

    AGGREGATION = 1
    """
    / All rows are aggregated into a single scalar.
    """

    TENSOR = 2
    """
    / Multiple rows in, multiple rows out.
    """


@dataclass(eq=False, repr=False)
class BundledRows(betterproto2.Message):
    """
    *
    A number of rows collected in one message. The actual number will depend on the size of each row and is adjusted to optimize throughput.
    """

    rows: "list[Row]" = betterproto2.field(1, betterproto2.TYPE_MESSAGE, repeated=True)


default_message_pool.register_message("qlik.sse", "BundledRows", BundledRows)


@dataclass(eq=False, repr=False)
class Capabilities(betterproto2.Message):
    """
    *
    A full description of the plugin, sent to the Qlik engine, listing all functions available and indicating whether script evaluation is allowed.
    """

    allow_script: "bool" = betterproto2.field(1, betterproto2.TYPE_BOOL)
    """
    / When true, the Qlik engine allows scripts to be sent to the plugin.
    """

    functions: "list[FunctionDefinition]" = betterproto2.field(
        2, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    / The definitions of all available functions.
    """

    plugin_identifier: "str" = betterproto2.field(3, betterproto2.TYPE_STRING)
    """
    / The ID or name of the plugin.
    """

    plugin_version: "str" = betterproto2.field(4, betterproto2.TYPE_STRING)
    """
    / The version of the plugin.
    """


default_message_pool.register_message("qlik.sse", "Capabilities", Capabilities)


@dataclass(eq=False, repr=False)
class CommonRequestHeader(betterproto2.Message):
    """
    *
    A header sent at the start of both an EvaluateScript request and an ExecuteFunction request under the key "qlik-commonrequestheader-bin".
    """

    app_id: "str" = betterproto2.field(1, betterproto2.TYPE_STRING)
    """
    / The ID of the app the request was executed in.
    """

    user_id: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / The ID of the user the request was executed by.
    """

    cardinality: "int" = betterproto2.field(3, betterproto2.TYPE_INT64)
    """
    / The cardinality of the parameters.
    """


default_message_pool.register_message(
    "qlik.sse", "CommonRequestHeader", CommonRequestHeader
)


@dataclass(eq=False, repr=False)
class Dual(betterproto2.Message):
    """
    *
    The basic data type for the data stream. Can contain double, string, or both.
    """

    num_data: "float" = betterproto2.field(1, betterproto2.TYPE_DOUBLE)
    """
    / Numeric value as double.
    """

    str_data: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / String.
    """


default_message_pool.register_message("qlik.sse", "Dual", Dual)


@dataclass(eq=False, repr=False)
class Empty(betterproto2.Message):
    """
    *
    An empty message used when nothing is to be passed in a call.
    """

    pass


default_message_pool.register_message("qlik.sse", "Empty", Empty)


@dataclass(eq=False, repr=False)
class FieldDescription(betterproto2.Message):
    """
    *
    Field definition for function and script calls.
    """

    data_type: "DataType" = betterproto2.field(
        1, betterproto2.TYPE_ENUM, default_factory=lambda: DataType(0)
    )
    """
    / The data type of the field.
    """

    name: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / The name of the field.
    """

    tags: "list[str]" = betterproto2.field(3, betterproto2.TYPE_STRING, repeated=True)
    """
    / The tags of the field.
    """


default_message_pool.register_message("qlik.sse", "FieldDescription", FieldDescription)


@dataclass(eq=False, repr=False)
class FunctionDefinition(betterproto2.Message):
    """
    *
    The definition of a function, which informs the Qlik engine how to use it.
    """

    name: "str" = betterproto2.field(1, betterproto2.TYPE_STRING)
    """
    / The name of the function.
    """

    function_type: "FunctionType" = betterproto2.field(
        2, betterproto2.TYPE_ENUM, default_factory=lambda: FunctionType(0)
    )
    """
    / The type of the function.
    """

    return_type: "DataType" = betterproto2.field(
        3, betterproto2.TYPE_ENUM, default_factory=lambda: DataType(0)
    )
    """
    / The return type of the function.
    """

    params: "list[Parameter]" = betterproto2.field(
        4, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    / The parameters the function takes.
    """

    function_id: "int" = betterproto2.field(5, betterproto2.TYPE_INT32)
    """
    / A unique ID number for the function, set by the plugin, to be used in calls from the Qlik engine to the plugin.
    """


default_message_pool.register_message(
    "qlik.sse", "FunctionDefinition", FunctionDefinition
)


@dataclass(eq=False, repr=False)
class FunctionRequestHeader(betterproto2.Message):
    """
    *
    A header sent at the start of an ExecuteFunction request under the key "qlik-functionrequestheader-bin".
    """

    function_id: "int" = betterproto2.field(1, betterproto2.TYPE_INT32)
    """
    / The ID of the function to be executed.
    """

    version: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / A dummy variable as a workaround for an issue.
    """


default_message_pool.register_message(
    "qlik.sse", "FunctionRequestHeader", FunctionRequestHeader
)


@dataclass(eq=False, repr=False)
class Parameter(betterproto2.Message):
    """
    *
    Parameter definition for functions and script calls.
    """

    data_type: "DataType" = betterproto2.field(
        1, betterproto2.TYPE_ENUM, default_factory=lambda: DataType(0)
    )
    """
    / The data type of the parameter.
    """

    name: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / The name of the parameter.
    """


default_message_pool.register_message("qlik.sse", "Parameter", Parameter)


@dataclass(eq=False, repr=False)
class Row(betterproto2.Message):
    """
    *
    A row of duals.
    """

    duals: "list[Dual]" = betterproto2.field(
        1, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    / Row of duals.
    """


default_message_pool.register_message("qlik.sse", "Row", Row)


@dataclass(eq=False, repr=False)
class ScriptRequestHeader(betterproto2.Message):
    """
    *
    A header sent at the start of an EvaluateScript request under the key "qlik-scriptrequestheader-bin".
    """

    script: "str" = betterproto2.field(1, betterproto2.TYPE_STRING)
    """
    / The script to be executed.
    """

    function_type: "FunctionType" = betterproto2.field(
        2, betterproto2.TYPE_ENUM, default_factory=lambda: FunctionType(0)
    )
    """
    / The function type of the script evaluation: scalar, aggregation or tensor.
    """

    return_type: "DataType" = betterproto2.field(
        3, betterproto2.TYPE_ENUM, default_factory=lambda: DataType(0)
    )
    """
    / The return type from the script evaluation: numeric, string or both.
    """

    params: "list[Parameter]" = betterproto2.field(
        4, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    / The parameters names and types passed to the script.
    """


default_message_pool.register_message(
    "qlik.sse", "ScriptRequestHeader", ScriptRequestHeader
)


@dataclass(eq=False, repr=False)
class TableDescription(betterproto2.Message):
    """
    *
    A header sent before returning data to Qlik, under the key "qlik-tabledescription-bin".
    """

    fields: "list[FieldDescription]" = betterproto2.field(
        1, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    / The fields of the table.
    """

    name: "str" = betterproto2.field(2, betterproto2.TYPE_STRING)
    """
    / The name of the table.
    """

    number_of_rows: "int" = betterproto2.field(3, betterproto2.TYPE_INT64)
    """
    / Number of rows in table.
    """


default_message_pool.register_message("qlik.sse", "TableDescription", TableDescription)


class ConnectorStub:
    """
    *
    The communication service provided between the Qlik engine and the plugin.
    """

    def __init__(self, channel: grpc.Channel):
        self._channel = channel

    def get_capabilities(self, message: "Empty | None" = None) -> "Capabilities":
        """
        / A handshake call for the Qlik engine to retrieve the capability of the plugin.
        """

        if message is None:
            message = Empty()

        return self._channel.unary_unary(
            "/qlik.sse.Connector/GetCapabilities",
            Empty.SerializeToString,
            Capabilities.FromString,
        )(message)

    def execute_function(
        self, messages: "Iterable[BundledRows]"
    ) -> "Iterator[BundledRows]":
        """
        / Requests a function to be executed as specified in the header.
        """

        yield from self._channel.stream_stream(
            "/qlik.sse.Connector/ExecuteFunction",
            BundledRows.SerializeToString,
            BundledRows.FromString,
        )(iter(messages))

    def evaluate_script(
        self, messages: "Iterable[BundledRows]"
    ) -> "Iterator[BundledRows]":
        """
        / Requests a script to be evaluated as specified in the header.
        """

        yield from self._channel.stream_stream(
            "/qlik.sse.Connector/EvaluateScript",
            BundledRows.SerializeToString,
            BundledRows.FromString,
        )(iter(messages))


class ConnectorBase(betterproto2_grpclib.ServiceBase):
    """
    *
    The communication service provided between the Qlik engine and the plugin.
    """

    async def get_capabilities(self, message: "Empty") -> "Capabilities":
        """
        / A handshake call for the Qlik engine to retrieve the capability of the plugin.
        """

        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def execute_function(
        self, messages: "AsyncIterator[BundledRows]"
    ) -> "AsyncIterator[BundledRows]":
        """
        / Requests a function to be executed as specified in the header.
        """

        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield BundledRows()

    async def evaluate_script(
        self, messages: "AsyncIterator[BundledRows]"
    ) -> "AsyncIterator[BundledRows]":
        """
        / Requests a script to be evaluated as specified in the header.
        """

        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield BundledRows()

    async def __rpc_get_capabilities(
        self, stream: "grpclib.server.Stream[Empty, Capabilities]"
    ) -> None:
        request = await stream.recv_message()
        assert request is not None
        response = await self.get_capabilities(request)
        await stream.send_message(response)

    async def __rpc_execute_function(
        self, stream: "grpclib.server.Stream[BundledRows, BundledRows]"
    ) -> None:
        request = stream.__aiter__()
        await self._call_rpc_handler_server_stream(
            self.execute_function,
            stream,
            request,
        )

    async def __rpc_evaluate_script(
        self, stream: "grpclib.server.Stream[BundledRows, BundledRows]"
    ) -> None:
        request = stream.__aiter__()
        await self._call_rpc_handler_server_stream(
            self.evaluate_script,
            stream,
            request,
        )

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/qlik.sse.Connector/GetCapabilities": grpclib.const.Handler(
                self.__rpc_get_capabilities,
                grpclib.const.Cardinality.UNARY_UNARY,
                Empty,
                Capabilities,
            ),
            "/qlik.sse.Connector/ExecuteFunction": grpclib.const.Handler(
                self.__rpc_execute_function,
                grpclib.const.Cardinality.STREAM_STREAM,
                BundledRows,
                BundledRows,
            ),
            "/qlik.sse.Connector/EvaluateScript": grpclib.const.Handler(
                self.__rpc_evaluate_script,
                grpclib.const.Cardinality.STREAM_STREAM,
                BundledRows,
                BundledRows,
            ),
        }
