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

__all__ = ("ListValue", "NullValue", "Struct", "Value")

import typing
from dataclasses import dataclass

import betterproto2

from ...message_pool import default_message_pool

_COMPILER_VERSION = "0.9.0"
betterproto2.check_compiler_version(_COMPILER_VERSION)


class NullValue(betterproto2.Enum):
    """
    `NullValue` is a singleton enumeration to represent the null value for the
    `Value` type union.

    The JSON representation for `NullValue` is JSON `null`.
    """

    NULL_VALUE = 0
    """
    Null value.
    """


@dataclass(eq=False, repr=False)
class ListValue(betterproto2.Message):
    """
    `ListValue` is a wrapper around a repeated field of values.

    The JSON representation for `ListValue` is JSON array.
    """

    values: "list[Value]" = betterproto2.field(
        1, betterproto2.TYPE_MESSAGE, repeated=True
    )
    """
    Repeated field of dynamically typed values.
    """

    @classmethod
    def from_dict(cls, value, *, ignore_unknown_fields: bool = False):
        return cls(values=[Value.from_dict(v) for v in value])

    def to_dict(
        self,
        *,
        output_format: betterproto2.OutputFormat = betterproto2.OutputFormat.PROTO_JSON,
        casing: betterproto2.Casing = betterproto2.Casing.CAMEL,
        include_default_values: bool = False,
    ) -> dict[str, typing.Any] | typing.Any:
        # If the output format is PYTHON, we should have kept the wrapped type without building the real class
        assert output_format == betterproto2.OutputFormat.PROTO_JSON

        return [value.to_dict() for value in self.values]


default_message_pool.register_message("google.protobuf", "ListValue", ListValue)


@dataclass(eq=False, repr=False)
class Struct(betterproto2.Message):
    """
    `Struct` represents a structured data value, consisting of fields
    which map to dynamically typed values. In some languages, `Struct`
    might be supported by a native representation. For example, in
    scripting languages like JS a struct is represented as an
    object. The details of that representation are described together
    with the proto support for the language.

    The JSON representation for `Struct` is JSON object.
    """

    fields: "dict[str, Value]" = betterproto2.field(
        1,
        betterproto2.TYPE_MAP,
        map_meta=betterproto2.map_meta(
            betterproto2.TYPE_STRING, betterproto2.TYPE_MESSAGE
        ),
    )
    """
    Unordered map of dynamically typed values.
    """

    @classmethod
    def from_dict(cls, value, *, ignore_unknown_fields: bool = False):
        assert isinstance(value, dict)

        fields: dict[str, Value] = {}

        for key, val in value.items():
            fields[key] = Value.from_dict(val)

        return cls(fields=fields)  # type: ignore[reportArgumentType]

    def to_dict(
        self,
        *,
        output_format: betterproto2.OutputFormat = betterproto2.OutputFormat.PROTO_JSON,
        casing: betterproto2.Casing = betterproto2.Casing.CAMEL,
        include_default_values: bool = False,
    ) -> dict[str, typing.Any] | typing.Any:
        # If the output format is PYTHON, we should have kept the wrapped type without building the real class
        assert output_format == betterproto2.OutputFormat.PROTO_JSON

        return {
            key: value.to_dict(
                output_format=output_format,
                casing=casing,
                include_default_values=include_default_values,
            )
            for key, value in self.fields.items()
        }


default_message_pool.register_message("google.protobuf", "Struct", Struct)


@dataclass(eq=False, repr=False)
class Value(betterproto2.Message):
    """
    `Value` represents a dynamically typed value which can be either
    null, a number, a string, a boolean, a recursive struct value, or a
    list of values. A producer of value is expected to set one of these
    variants. Absence of any variant indicates an error.

    The JSON representation for `Value` is JSON value.

    Oneofs:
        - kind: The kind of value.
    """

    null_value: "NullValue | None" = betterproto2.field(
        1, betterproto2.TYPE_ENUM, optional=True, group="kind"
    )
    """
    Represents a null value.
    """

    number_value: "float | None" = betterproto2.field(
        2, betterproto2.TYPE_DOUBLE, optional=True, group="kind"
    )
    """
    Represents a double value.
    """

    string_value: "str | None" = betterproto2.field(
        3, betterproto2.TYPE_STRING, optional=True, group="kind"
    )
    """
    Represents a string value.
    """

    bool_value: "bool | None" = betterproto2.field(
        4, betterproto2.TYPE_BOOL, optional=True, group="kind"
    )
    """
    Represents a boolean value.
    """

    struct_value: "Struct | None" = betterproto2.field(
        5, betterproto2.TYPE_MESSAGE, optional=True, group="kind"
    )
    """
    Represents a structured value.
    """

    list_value: "ListValue | None" = betterproto2.field(
        6, betterproto2.TYPE_MESSAGE, optional=True, group="kind"
    )
    """
    Represents a repeated `Value`.
    """

    @classmethod
    def from_dict(cls, value, *, ignore_unknown_fields: bool = False):
        match value:
            case bool() as b:
                return cls(bool_value=b)
            case int() | float() as num:
                return cls(number_value=num)
            case str() as s:
                return cls(string_value=s)
            case list() as l:
                return cls(list_value=ListValue.from_dict(l))
            case dict() as d:
                return cls(struct_value=Struct.from_dict(d))
            case None:
                return cls(null_value=NullValue.NULL_VALUE)
        raise ValueError(f"Unknown value type: {type(value)}")

    def to_dict(
        self,
        *,
        output_format: betterproto2.OutputFormat = betterproto2.OutputFormat.PROTO_JSON,
        casing: betterproto2.Casing = betterproto2.Casing.CAMEL,
        include_default_values: bool = False,
    ) -> dict[str, typing.Any] | typing.Any:
        # If the output format is PYTHON, we should have kept the wrapped type without building the real class
        assert output_format == betterproto2.OutputFormat.PROTO_JSON

        match self:
            case Value(null_value=NullValue.NULL_VALUE):
                return None
            case Value(bool_value=bool(b)):
                return b
            case Value(number_value=int(num)) | Value(number_value=float(num)):
                return num
            case Value(string_value=str(s)):
                return s
            case Value(list_value=ListValue(values=l)):
                return [v.to_dict() for v in l]
            case Value(struct_value=Struct(fields=f)):
                return {k: v.to_dict() for k, v in f.items()}

        raise ValueError("Invalid value")


default_message_pool.register_message("google.protobuf", "Value", Value)
