"""
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 binance_common.errors import RequiredError
from binance_common.models import WebsocketApiResponse
from binance_common.signature import Signers
from binance_common.websocket import WebSocketAPIBase

from ..models import AvgPriceResponse
from ..models import DepthResponse
from ..models import KlinesResponse
from ..models import TickerResponse
from ..models import Ticker24hrResponse
from ..models import TickerBookResponse
from ..models import TickerPriceResponse
from ..models import TickerTradingDayResponse
from ..models import TradesAggregateResponse
from ..models import TradesHistoricalResponse
from ..models import TradesRecentResponse
from ..models import UiKlinesResponse


from ..models import DepthSymbolStatusEnum
from ..models import KlinesIntervalEnum
from ..models import TickerTypeEnum
from ..models import TickerWindowSizeEnum
from ..models import TickerSymbolStatusEnum
from ..models import Ticker24hrTypeEnum
from ..models import Ticker24hrSymbolStatusEnum
from ..models import TickerBookSymbolStatusEnum
from ..models import TickerPriceSymbolStatusEnum
from ..models import TickerTradingDayTypeEnum
from ..models import TickerTradingDaySymbolStatusEnum
from ..models import UiKlinesIntervalEnum

from typing import List, Optional, Union


class MarketApi:
    """API Client for MarketApi endpoints."""

    def __init__(
        self,
        websocket_api: WebSocketAPIBase,
        signer: Signers = None,
    ) -> None:
        self.websocket_api = websocket_api
        self.signer = signer

    async def avg_price(
        self,
        symbol: Union[str, None],
        id: Optional[str] = None,
    ) -> WebsocketApiResponse[AvgPriceResponse]:
        """
            WebSocket Current average price
            /avgPrice
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#current-average-price

            Get current average price for a symbol.
        Weight: 2

            Args:
                    symbol (Union[str, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.

            Returns:
                WebsocketApiResponse[AvgPriceResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )

        params = {
            "symbol": symbol,
            **({"id": id} if id is not None else {}),
        }

        payload = {
            "method": "/avgPrice".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=AvgPriceResponse
        )

    async def depth(
        self,
        symbol: Union[str, None],
        id: Optional[str] = None,
        limit: Optional[int] = None,
        symbol_status: Optional[DepthSymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[DepthResponse]:
        """
            WebSocket Order book
            /depth
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#order-book

            Get current order book.

        Note that this request returns limited market depth.

        If you need to continuously monitor order book updates, please consider using WebSocket Streams:

        * `<symbol>@depth<levels>`
        * `<symbol>@depth`

        You can use `depth` request together with `<symbol>@depth` streams to [maintain a local order book](web-socket-streams.md#how-to-manage-a-local-order-book-correctly).
        Weight: Adjusted based on the limit:

        |  Limit    | Weight |
        |:---------:|:------:|
        |     1–100 |      5 |
        |   101–500 |      25|
        |  501–1000 |     50 |
        | 1001–5000 |     250 |

            Args:
                    symbol (Union[str, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    limit (Optional[int] = None): Default: 100; Maximum: 5000
                    symbol_status (Optional[DepthSymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[DepthResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )

        params = {
            "symbol": symbol,
            **({"id": id} if id is not None else {}),
            **({"limit": limit} if limit is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/depth".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=DepthResponse
        )

    async def klines(
        self,
        symbol: Union[str, None],
        interval: Union[KlinesIntervalEnum, None],
        id: Optional[str] = None,
        start_time: Optional[int] = None,
        end_time: Optional[int] = None,
        time_zone: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> WebsocketApiResponse[KlinesResponse]:
        """
            WebSocket Klines
            /klines
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines

            Get klines (candlestick bars).

        Klines are uniquely identified by their open & close time.

        If you need access to real-time kline updates, please consider using WebSocket Streams:

        * `<symbol>@kline_<interval>`

        If you need historical kline data,
        please consider using [data.binance.vision](https://github.com/binance/binance-public-data/#klines).
        Weight: 2

            Args:
                    symbol (Union[str, None]):
                    interval (Union[KlinesIntervalEnum, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    start_time (Optional[int] = None):
                    end_time (Optional[int] = None):
                    time_zone (Optional[str] = None): Default: 0 (UTC)
                    limit (Optional[int] = None): Default: 100; Maximum: 5000

            Returns:
                WebsocketApiResponse[KlinesResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )
        if interval is None:
            raise RequiredError(
                field="interval", error_message="Missing required parameter 'interval'"
            )

        params = {
            "symbol": symbol,
            "interval": interval,
            **({"id": id} if id is not None else {}),
            **({"start_time": start_time} if start_time is not None else {}),
            **({"end_time": end_time} if end_time is not None else {}),
            **({"time_zone": time_zone} if time_zone is not None else {}),
            **({"limit": limit} if limit is not None else {}),
        }

        payload = {
            "method": "/klines".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=KlinesResponse
        )

    async def ticker(
        self,
        id: Optional[str] = None,
        symbol: Optional[str] = None,
        symbols: Optional[List[str]] = None,
        type: Optional[TickerTypeEnum] = None,
        window_size: Optional[TickerWindowSizeEnum] = None,
        symbol_status: Optional[TickerSymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[TickerResponse]:
        """
            WebSocket Rolling window price change statistics
            /ticker
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#rolling-window-price-change-statistics

            Get rolling window price change statistics with a custom window.

        This request is similar to `ticker.24hr`,
        but statistics are computed on demand using the arbitrary window you specify.
        Weight: Adjusted based on the number of requested symbols:

        | Symbols | Weight |
        |:-------:|:------:|
        |    1–50 | 4 per symbol |
        |  51–100 |    200 |

            Args:
                    id (Optional[str] = None): Unique WebSocket request ID.
                    symbol (Optional[str] = None): Describe a single symbol
                    symbols (Optional[List[str]] = None): List of symbols to query
                    type (Optional[TickerTypeEnum] = None):
                    window_size (Optional[TickerWindowSizeEnum] = None):
                    symbol_status (Optional[TickerSymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[TickerResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        params = {
            **({"id": id} if id is not None else {}),
            **({"symbol": symbol} if symbol is not None else {}),
            **({"symbols": symbols} if symbols is not None else {}),
            **({"type": type} if type is not None else {}),
            **({"window_size": window_size} if window_size is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/ticker".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TickerResponse
        )

    async def ticker24hr(
        self,
        id: Optional[str] = None,
        symbol: Optional[str] = None,
        symbols: Optional[List[str]] = None,
        type: Optional[Ticker24hrTypeEnum] = None,
        symbol_status: Optional[Ticker24hrSymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[Ticker24hrResponse]:
        """
            WebSocket 24hr ticker price change statistics
            /ticker.24hr
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#24hr-ticker-price-change-statistics

            Get 24-hour rolling window price change statistics.

        If you need to continuously monitor trading statistics, please consider using WebSocket Streams:

        * `<symbol>@ticker` or `!ticker@arr`
        * `<symbol>@miniTicker` or `!miniTicker@arr`

        If you need different window sizes,
        use the `ticker` request.
        Weight: Adjusted based on the number of requested symbols:

        | Symbols     | Weight |
        |:-----------:|:------:|
        |        1–20 |      2 |
        |      21–100 |     40 |
        | 101 or more |     80 |
        | all symbols |     80 |

            Args:
                    id (Optional[str] = None): Unique WebSocket request ID.
                    symbol (Optional[str] = None): Describe a single symbol
                    symbols (Optional[List[str]] = None): List of symbols to query
                    type (Optional[Ticker24hrTypeEnum] = None):
                    symbol_status (Optional[Ticker24hrSymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[Ticker24hrResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        params = {
            **({"id": id} if id is not None else {}),
            **({"symbol": symbol} if symbol is not None else {}),
            **({"symbols": symbols} if symbols is not None else {}),
            **({"type": type} if type is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/ticker.24hr".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=Ticker24hrResponse
        )

    async def ticker_book(
        self,
        id: Optional[str] = None,
        symbol: Optional[str] = None,
        symbols: Optional[List[str]] = None,
        symbol_status: Optional[TickerBookSymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[TickerBookResponse]:
        """
            WebSocket Symbol order book ticker
            /ticker.book
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#symbol-order-book-ticker

            Get the current best price and quantity on the order book.

        If you need access to real-time order book ticker updates, please consider using WebSocket Streams:

        * `<symbol>@bookTicker`
        Weight: Adjusted based on the number of requested symbols:

        | Parameter | Weight |
        | --------- |:------:|
        | `symbol`  |      2 |
        | `symbols` |      4 |
        | none      |      4 |

            Args:
                    id (Optional[str] = None): Unique WebSocket request ID.
                    symbol (Optional[str] = None): Describe a single symbol
                    symbols (Optional[List[str]] = None): List of symbols to query
                    symbol_status (Optional[TickerBookSymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[TickerBookResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        params = {
            **({"id": id} if id is not None else {}),
            **({"symbol": symbol} if symbol is not None else {}),
            **({"symbols": symbols} if symbols is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/ticker.book".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TickerBookResponse
        )

    async def ticker_price(
        self,
        id: Optional[str] = None,
        symbol: Optional[str] = None,
        symbols: Optional[List[str]] = None,
        symbol_status: Optional[TickerPriceSymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[TickerPriceResponse]:
        """
            WebSocket Symbol price ticker
            /ticker.price
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#symbol-price-ticker

            Get the latest market price for a symbol.

        If you need access to real-time price updates, please consider using WebSocket Streams:

        * `<symbol>@aggTrade`
        * `<symbol>@trade`
        Weight: Adjusted based on the number of requested symbols:

        | Parameter | Weight |
        | --------- |:------:|
        | `symbol`  |      2 |
        | `symbols` |      4 |
        | none      |      4 |

            Args:
                    id (Optional[str] = None): Unique WebSocket request ID.
                    symbol (Optional[str] = None): Describe a single symbol
                    symbols (Optional[List[str]] = None): List of symbols to query
                    symbol_status (Optional[TickerPriceSymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[TickerPriceResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        params = {
            **({"id": id} if id is not None else {}),
            **({"symbol": symbol} if symbol is not None else {}),
            **({"symbols": symbols} if symbols is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/ticker.price".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TickerPriceResponse
        )

    async def ticker_trading_day(
        self,
        id: Optional[str] = None,
        symbol: Optional[str] = None,
        symbols: Optional[List[str]] = None,
        time_zone: Optional[str] = None,
        type: Optional[TickerTradingDayTypeEnum] = None,
        symbol_status: Optional[TickerTradingDaySymbolStatusEnum] = None,
    ) -> WebsocketApiResponse[TickerTradingDayResponse]:
        """
            WebSocket Trading Day Ticker
            /ticker.tradingDay
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#trading-day-ticker

            Price change statistics for a trading day.
        Weight: 4 for each requested <tt>symbol</tt>. <br/><br/> The weight for this request will cap at 200 once the number of `symbols` in the request is more than 50.

            Args:
                    id (Optional[str] = None): Unique WebSocket request ID.
                    symbol (Optional[str] = None): Describe a single symbol
                    symbols (Optional[List[str]] = None): List of symbols to query
                    time_zone (Optional[str] = None): Default: 0 (UTC)
                    type (Optional[TickerTradingDayTypeEnum] = None):
                    symbol_status (Optional[TickerTradingDaySymbolStatusEnum] = None):

            Returns:
                WebsocketApiResponse[TickerTradingDayResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        params = {
            **({"id": id} if id is not None else {}),
            **({"symbol": symbol} if symbol is not None else {}),
            **({"symbols": symbols} if symbols is not None else {}),
            **({"time_zone": time_zone} if time_zone is not None else {}),
            **({"type": type} if type is not None else {}),
            **({"symbol_status": symbol_status} if symbol_status is not None else {}),
        }

        payload = {
            "method": "/ticker.tradingDay".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TickerTradingDayResponse
        )

    async def trades_aggregate(
        self,
        symbol: Union[str, None],
        id: Optional[str] = None,
        from_id: Optional[int] = None,
        start_time: Optional[int] = None,
        end_time: Optional[int] = None,
        limit: Optional[int] = None,
    ) -> WebsocketApiResponse[TradesAggregateResponse]:
        """
            WebSocket Aggregate trades
            /trades.aggregate
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#aggregate-trades

            Get aggregate trades.

        An *aggregate trade* (aggtrade) represents one or more individual trades.
        Trades that fill at the same time, from the same taker order, with the same price –
        those trades are collected into an aggregate trade with total quantity of the individual trades.

        If you need access to real-time trading activity, please consider using WebSocket Streams:

        * `<symbol>@aggTrade`

        If you need historical aggregate trade data,
        please consider using [data.binance.vision](https://github.com/binance/binance-public-data/#aggtrades).
        Weight: 4

            Args:
                    symbol (Union[str, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    from_id (Optional[int] = None): Aggregate trade ID to begin at
                    start_time (Optional[int] = None):
                    end_time (Optional[int] = None):
                    limit (Optional[int] = None): Default: 100; Maximum: 5000

            Returns:
                WebsocketApiResponse[TradesAggregateResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )

        params = {
            "symbol": symbol,
            **({"id": id} if id is not None else {}),
            **({"from_id": from_id} if from_id is not None else {}),
            **({"start_time": start_time} if start_time is not None else {}),
            **({"end_time": end_time} if end_time is not None else {}),
            **({"limit": limit} if limit is not None else {}),
        }

        payload = {
            "method": "/trades.aggregate".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TradesAggregateResponse
        )

    async def trades_historical(
        self,
        symbol: Union[str, None],
        id: Optional[str] = None,
        from_id: Optional[int] = None,
        limit: Optional[int] = None,
    ) -> WebsocketApiResponse[TradesHistoricalResponse]:
        """
            WebSocket Historical trades
            /trades.historical
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#historical-trades

            Get historical trades.
        Weight: 25

            Args:
                    symbol (Union[str, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    from_id (Optional[int] = None): Aggregate trade ID to begin at
                    limit (Optional[int] = None): Default: 100; Maximum: 5000

            Returns:
                WebsocketApiResponse[TradesHistoricalResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )

        params = {
            "symbol": symbol,
            **({"id": id} if id is not None else {}),
            **({"from_id": from_id} if from_id is not None else {}),
            **({"limit": limit} if limit is not None else {}),
        }

        payload = {
            "method": "/trades.historical".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TradesHistoricalResponse
        )

    async def trades_recent(
        self,
        symbol: Union[str, None],
        id: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> WebsocketApiResponse[TradesRecentResponse]:
        """
            WebSocket Recent trades
            /trades.recent
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades

            Get recent trades.

        If you need access to real-time trading activity, please consider using WebSocket Streams:

        * `<symbol>@trade`
        Weight: 25

            Args:
                    symbol (Union[str, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    limit (Optional[int] = None): Default: 100; Maximum: 5000

            Returns:
                WebsocketApiResponse[TradesRecentResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )

        params = {
            "symbol": symbol,
            **({"id": id} if id is not None else {}),
            **({"limit": limit} if limit is not None else {}),
        }

        payload = {
            "method": "/trades.recent".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=TradesRecentResponse
        )

    async def ui_klines(
        self,
        symbol: Union[str, None],
        interval: Union[UiKlinesIntervalEnum, None],
        id: Optional[str] = None,
        start_time: Optional[int] = None,
        end_time: Optional[int] = None,
        time_zone: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> WebsocketApiResponse[UiKlinesResponse]:
        """
            WebSocket UI Klines
            /uiKlines
            https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#ui-klines

            Get klines (candlestick bars) optimized for presentation.

        This request is similar to `klines`, having the same parameters and response.
        `uiKlines` return modified kline data, optimized for presentation of candlestick charts.
        Weight: 2

            Args:
                    symbol (Union[str, None]):
                    interval (Union[UiKlinesIntervalEnum, None]):
                    id (Optional[str] = None): Unique WebSocket request ID.
                    start_time (Optional[int] = None):
                    end_time (Optional[int] = None):
                    time_zone (Optional[str] = None): Default: 0 (UTC)
                    limit (Optional[int] = None): Default: 100; Maximum: 5000

            Returns:
                WebsocketApiResponse[UiKlinesResponse]

            Raises:
                RequiredError: If a required parameter is missing.

        """

        if symbol is None:
            raise RequiredError(
                field="symbol", error_message="Missing required parameter 'symbol'"
            )
        if interval is None:
            raise RequiredError(
                field="interval", error_message="Missing required parameter 'interval'"
            )

        params = {
            "symbol": symbol,
            "interval": interval,
            **({"id": id} if id is not None else {}),
            **({"start_time": start_time} if start_time is not None else {}),
            **({"end_time": end_time} if end_time is not None else {}),
            **({"time_zone": time_zone} if time_zone is not None else {}),
            **({"limit": limit} if limit is not None else {}),
        }

        payload = {
            "method": "/uiKlines".replace("/", "", 1),
            "params": params,
        }

        return await self.websocket_api.send_message(
            payload=payload, response_model=UiKlinesResponse
        )
