# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: blickfeld/diagnostics/services/report.proto, blickfeld/diagnostics/services/self_test.proto
# plugin: python-betterproto
import asyncio
from dataclasses import dataclass
from typing import (
    TYPE_CHECKING,
    AsyncIterator,
    Dict,
    Iterator,
    List,
    Optional,
)

import blickfeld_qb2.betterproto as betterproto
import blickfeld_qb2.betterproto.lib.google.protobuf as betterproto_lib_google_protobuf
import grpclib
from blickfeld_qb2.betterproto.grpc.grpclib_server import ServiceBase

from .. import (
    config as _config__,
    data as _data__,
)


if TYPE_CHECKING:
    import grpclib.server
    from blickfeld_qb2.betterproto.grpc.grpclib_client import MetadataLike
    from grpclib.metadata import Deadline


@dataclass(eq=False, repr=False)
class ReportGenerateResponse(betterproto.Message):
    """Stream of the encrypted report in chunks of binary data"""

    binary_chunk: bytes = betterproto.bytes_field(1)
    """Binary chunk of the diagnostics report."""


@dataclass(eq=False, repr=False)
class SelfTestRunRequest(betterproto.Message):
    """The self test run can be configured with this request"""

    self_tests: List["_config__.SelfTest"] = betterproto.enum_field(1)
    """
    Specify self tests which should be executed. If not set, the default set
    will be executed.
    """


@dataclass(eq=False, repr=False)
class SelfTestRunResponse(betterproto.Message):
    """
    The response provides the self test report. [NOTE] The method will not
    throw an exception on API level if tests failed or have warnings. The
    success flag in the report must be checked.
    """

    report: "_data__.SelfTestReport" = betterproto.message_field(1)
    """Test report"""


class Report(betterproto.ServiceStub):
    """
    The Report service generates an encrypted diagnostics report containing
    information about the state and health information of the Qb2 device.
    """

    async def async_generate(
        self,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None,
    ) -> AsyncIterator["ReportGenerateResponse"]:
        """Returns a stream of the report's binary chunks"""

        request = betterproto_lib_google_protobuf.Empty()

        async for response in self._unary_stream(
            "/blickfeld.diagnostics.services.Report/Generate",
            request,
            ReportGenerateResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    def generate(
        self,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None,
    ) -> Iterator["ReportGenerateResponse"]:
        """Returns a stream of the report's binary chunks"""

        loop = asyncio.get_event_loop()
        ait = self.async_generate(
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ).__aiter__()

        async def get_next():
            try:
                obj = await ait.__anext__()
                return False, obj
            except StopAsyncIteration:
                return True, None

        while True:
            done, obj = loop.run_until_complete(get_next())
            if done:
                break
            yield obj


class SelfTest(betterproto.ServiceStub):
    """
    The SelfTest service offers methods to trigger test routines. The routines
    focus on automatic self tests without user interaction. The reports give an
    indication what the potential root cause for an found issue could be.
    """

    async def async_run(
        self,
        *,
        self_tests: Optional[List["_config__.SelfTest"]] = None,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "SelfTestRunResponse":
        """This triggers the default test case routine"""

        self_tests = self_tests or []

        request = SelfTestRunRequest()
        request.self_tests = self_tests

        return await self._unary_unary(
            "/blickfeld.diagnostics.services.SelfTest/Run",
            request,
            SelfTestRunResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    def run(
        self,
        *,
        self_tests: Optional[List["_config__.SelfTest"]] = None,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "SelfTestRunResponse":
        """This triggers the default test case routine"""

        loop = asyncio.get_event_loop()
        return loop.run_until_complete(
            self.async_run(
                self_tests=self_tests,
                timeout=timeout,
                deadline=deadline,
                metadata=metadata,
            )
        )
