# coding: utf-8

"""
Binance Spot WebSocket API

OpenAPI Specifications for the Binance Spot WebSocket API

API documents:
  - [Github web-socket-api documentation file](https://github.com/binance/binance-spot-api-docs/blob/master/web-socket-api.md)
  - [General API information for web-socket-api on website](https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api/general-api-information)

The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""


from __future__ import annotations
import json
import pprint
from pydantic import (
    BaseModel,
    ConfigDict,
    ValidationError,
)
from typing import Any, Optional
from binance_sdk_spot.websocket_api.models.iceberg_parts_filter import (
    IcebergPartsFilter,
)
from binance_sdk_spot.websocket_api.models.lot_size_filter import LotSizeFilter
from binance_sdk_spot.websocket_api.models.market_lot_size_filter import (
    MarketLotSizeFilter,
)
from binance_sdk_spot.websocket_api.models.max_num_algo_orders_filter import (
    MaxNumAlgoOrdersFilter,
)
from binance_sdk_spot.websocket_api.models.max_num_iceberg_orders_filter import (
    MaxNumIcebergOrdersFilter,
)
from binance_sdk_spot.websocket_api.models.max_num_order_amends_filter import (
    MaxNumOrderAmendsFilter,
)
from binance_sdk_spot.websocket_api.models.max_num_order_lists_filter import (
    MaxNumOrderListsFilter,
)
from binance_sdk_spot.websocket_api.models.max_num_orders_filter import (
    MaxNumOrdersFilter,
)
from binance_sdk_spot.websocket_api.models.max_position_filter import MaxPositionFilter
from binance_sdk_spot.websocket_api.models.min_notional_filter import MinNotionalFilter
from binance_sdk_spot.websocket_api.models.notional_filter import NotionalFilter
from binance_sdk_spot.websocket_api.models.percent_price_by_side_filter import (
    PercentPriceBySideFilter,
)
from binance_sdk_spot.websocket_api.models.percent_price_filter import (
    PercentPriceFilter,
)
from binance_sdk_spot.websocket_api.models.price_filter import PriceFilter
from binance_sdk_spot.websocket_api.models.t_plus_sell_filter import TPlusSellFilter
from binance_sdk_spot.websocket_api.models.trailing_delta_filter import (
    TrailingDeltaFilter,
)
from typing import Union, Set, Dict
from typing_extensions import Self

SYMBOLFILTERS_ONE_OF_SCHEMAS = [
    "IcebergPartsFilter",
    "LotSizeFilter",
    "MarketLotSizeFilter",
    "MaxNumAlgoOrdersFilter",
    "MaxNumIcebergOrdersFilter",
    "MaxNumOrderAmendsFilter",
    "MaxNumOrderListsFilter",
    "MaxNumOrdersFilter",
    "MaxPositionFilter",
    "MinNotionalFilter",
    "NotionalFilter",
    "PercentPriceBySideFilter",
    "PercentPriceFilter",
    "PriceFilter",
    "TPlusSellFilter",
    "TrailingDeltaFilter",
]


class SymbolFilters(BaseModel):
    """
    SymbolFilters
    """

    # data type: PriceFilter
    oneof_schema_1_validator: Optional[PriceFilter] = None
    # data type: PercentPriceFilter
    oneof_schema_2_validator: Optional[PercentPriceFilter] = None
    # data type: PercentPriceBySideFilter
    oneof_schema_3_validator: Optional[PercentPriceBySideFilter] = None
    # data type: LotSizeFilter
    oneof_schema_4_validator: Optional[LotSizeFilter] = None
    # data type: MinNotionalFilter
    oneof_schema_5_validator: Optional[MinNotionalFilter] = None
    # data type: NotionalFilter
    oneof_schema_6_validator: Optional[NotionalFilter] = None
    # data type: IcebergPartsFilter
    oneof_schema_7_validator: Optional[IcebergPartsFilter] = None
    # data type: MarketLotSizeFilter
    oneof_schema_8_validator: Optional[MarketLotSizeFilter] = None
    # data type: MaxNumOrdersFilter
    oneof_schema_9_validator: Optional[MaxNumOrdersFilter] = None
    # data type: MaxNumAlgoOrdersFilter
    oneof_schema_10_validator: Optional[MaxNumAlgoOrdersFilter] = None
    # data type: MaxNumIcebergOrdersFilter
    oneof_schema_11_validator: Optional[MaxNumIcebergOrdersFilter] = None
    # data type: MaxPositionFilter
    oneof_schema_12_validator: Optional[MaxPositionFilter] = None
    # data type: TrailingDeltaFilter
    oneof_schema_13_validator: Optional[TrailingDeltaFilter] = None
    # data type: TPlusSellFilter
    oneof_schema_14_validator: Optional[TPlusSellFilter] = None
    # data type: MaxNumOrderListsFilter
    oneof_schema_15_validator: Optional[MaxNumOrderListsFilter] = None
    # data type: MaxNumOrderAmendsFilter
    oneof_schema_16_validator: Optional[MaxNumOrderAmendsFilter] = None
    actual_instance: Optional[
        Union[
            PriceFilter,
            PercentPriceFilter,
            PercentPriceBySideFilter,
            LotSizeFilter,
            MinNotionalFilter,
            NotionalFilter,
            IcebergPartsFilter,
            MarketLotSizeFilter,
            MaxNumOrdersFilter,
            MaxNumAlgoOrdersFilter,
            MaxNumIcebergOrdersFilter,
            MaxPositionFilter,
            TrailingDeltaFilter,
            TPlusSellFilter,
            MaxNumOrderListsFilter,
            MaxNumOrderAmendsFilter,
        ]
    ] = None
    one_of_schemas: Set[str] = {
        "IcebergPartsFilter",
        "LotSizeFilter",
        "MarketLotSizeFilter",
        "MaxNumAlgoOrdersFilter",
        "MaxNumIcebergOrdersFilter",
        "MaxNumOrderAmendsFilter",
        "MaxNumOrderListsFilter",
        "MaxNumOrdersFilter",
        "MaxPositionFilter",
        "MinNotionalFilter",
        "NotionalFilter",
        "PercentPriceBySideFilter",
        "PercentPriceFilter",
        "PriceFilter",
        "TPlusSellFilter",
        "TrailingDeltaFilter",
    }

    model_config = ConfigDict(
        validate_assignment=True,
        protected_namespaces=(),
    )

    discriminator_value_class_map: Dict[str, str] = {}

    def __init__(self, *args, **kwargs) -> None:
        if args:
            if len(args) > 1:
                raise ValueError(
                    "If a position argument is used, only 1 is allowed to set `actual_instance`"
                )
            if kwargs:
                raise ValueError(
                    "If a position argument is used, keyword arguments cannot be used."
                )
            super().__init__(actual_instance=args[0])
        else:
            super().__init__(**kwargs)

    @classmethod
    def is_oneof_model(cls) -> bool:
        return True

    @classmethod
    def from_dict(cls, parsed) -> Self:
        """Returns the object represented by the json string"""
        instance = cls.model_construct()
        error_messages = []
        match = 0

        is_list = isinstance(parsed, list)

        # deserialize data into PriceFilter
        if is_list == PriceFilter.is_array():
            try:
                instance.actual_instance = PriceFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into PercentPriceFilter
        if is_list == PercentPriceFilter.is_array():
            try:
                instance.actual_instance = PercentPriceFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into PercentPriceBySideFilter
        if is_list == PercentPriceBySideFilter.is_array():
            try:
                instance.actual_instance = PercentPriceBySideFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into LotSizeFilter
        if is_list == LotSizeFilter.is_array():
            try:
                instance.actual_instance = LotSizeFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MinNotionalFilter
        if is_list == MinNotionalFilter.is_array():
            try:
                instance.actual_instance = MinNotionalFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into NotionalFilter
        if is_list == NotionalFilter.is_array():
            try:
                instance.actual_instance = NotionalFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into IcebergPartsFilter
        if is_list == IcebergPartsFilter.is_array():
            try:
                instance.actual_instance = IcebergPartsFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MarketLotSizeFilter
        if is_list == MarketLotSizeFilter.is_array():
            try:
                instance.actual_instance = MarketLotSizeFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxNumOrdersFilter
        if is_list == MaxNumOrdersFilter.is_array():
            try:
                instance.actual_instance = MaxNumOrdersFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxNumAlgoOrdersFilter
        if is_list == MaxNumAlgoOrdersFilter.is_array():
            try:
                instance.actual_instance = MaxNumAlgoOrdersFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxNumIcebergOrdersFilter
        if is_list == MaxNumIcebergOrdersFilter.is_array():
            try:
                instance.actual_instance = MaxNumIcebergOrdersFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxPositionFilter
        if is_list == MaxPositionFilter.is_array():
            try:
                instance.actual_instance = MaxPositionFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into TrailingDeltaFilter
        if is_list == TrailingDeltaFilter.is_array():
            try:
                instance.actual_instance = TrailingDeltaFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into TPlusSellFilter
        if is_list == TPlusSellFilter.is_array():
            try:
                instance.actual_instance = TPlusSellFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxNumOrderListsFilter
        if is_list == MaxNumOrderListsFilter.is_array():
            try:
                instance.actual_instance = MaxNumOrderListsFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))
        # deserialize data into MaxNumOrderAmendsFilter
        if is_list == MaxNumOrderAmendsFilter.is_array():
            try:
                instance.actual_instance = MaxNumOrderAmendsFilter.from_dict(parsed)
                match += 1
            except (ValidationError, ValueError) as e:
                error_messages.append(str(e))

        if match > 1:
            # more than 1 match
            raise ValueError(
                "Multiple matches found when deserializing the JSON string into SymbolFilters with oneOf schemas: IcebergPartsFilter, LotSizeFilter, MarketLotSizeFilter, MaxNumAlgoOrdersFilter, MaxNumIcebergOrdersFilter, MaxNumOrderAmendsFilter, MaxNumOrderListsFilter, MaxNumOrdersFilter, MaxPositionFilter, MinNotionalFilter, NotionalFilter, PercentPriceBySideFilter, PercentPriceFilter, PriceFilter, TPlusSellFilter, TrailingDeltaFilter. Details: "
                + ", ".join(error_messages)
            )
        elif match == 0:
            # no match
            raise ValueError(
                "No match found when deserializing the JSON string into SymbolFilters with oneOf schemas: IcebergPartsFilter, LotSizeFilter, MarketLotSizeFilter, MaxNumAlgoOrdersFilter, MaxNumIcebergOrdersFilter, MaxNumOrderAmendsFilter, MaxNumOrderListsFilter, MaxNumOrdersFilter, MaxPositionFilter, MinNotionalFilter, NotionalFilter, PercentPriceBySideFilter, PercentPriceFilter, PriceFilter, TPlusSellFilter, TrailingDeltaFilter. Details: "
                + ", ".join(error_messages)
            )
        else:
            return instance

    def to_json(self) -> str:
        """Returns the JSON representation of the actual instance"""
        if self.actual_instance is None:
            return "null"

        if hasattr(self.actual_instance, "to_json") and callable(
            self.actual_instance.to_json
        ):
            return self.actual_instance.to_json()
        else:
            return json.dumps(self.actual_instance)

    def to_dict(
        self,
    ) -> Optional[
        Union[
            Dict[str, Any],
            IcebergPartsFilter,
            LotSizeFilter,
            MarketLotSizeFilter,
            MaxNumAlgoOrdersFilter,
            MaxNumIcebergOrdersFilter,
            MaxNumOrderAmendsFilter,
            MaxNumOrderListsFilter,
            MaxNumOrdersFilter,
            MaxPositionFilter,
            MinNotionalFilter,
            NotionalFilter,
            PercentPriceBySideFilter,
            PercentPriceFilter,
            PriceFilter,
            TPlusSellFilter,
            TrailingDeltaFilter,
        ]
    ]:
        """Returns the dict representation of the actual instance"""
        if self.actual_instance is None:
            return None

        if hasattr(self.actual_instance, "to_dict") and callable(
            self.actual_instance.to_dict
        ):
            return self.actual_instance.to_dict()
        else:
            # primitive type
            return self.actual_instance

    def to_str(self) -> str:
        """Returns the string representation of the actual instance"""
        return pprint.pformat(self.model_dump())
