# -*- coding: utf-8 -*-

# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code

import ccxt.async_support
from ccxt.base.types import Int, OrderBook, Ticker, Trade
from ccxt.async_support.base.ws.client import Client
from typing import List


class idax(ccxt.async_support.idax):

    def describe(self):
        return self.deep_extend(super(idax, self).describe(), {
            'has': {
                'ws': True,
                'watchBalance': False,
                'watchMyTrades': False,
                'watchOHLCV': True,
                'watchOHLCVForSymbols': False,
                'watchOrderBook': True,
                'watchOrderBookForSymbols': False,
                'watchOrders': False,
                'watchOrdersForSymbols': False,
                'watchPositions': False,
                'watchTicker': True,
                'watchTickers': False,
                'watchTrades': True,
                'watchTradesForSymbols': False,
            },
            'urls': {
                'api': {
                    'ws': 'wss://ws.idax.exchange/kline-api/ws',
                },
            },
            'streaming': {
                'keepAlive': 180000,
            },
            'options': {
                'ws': {
                    'gunzip': True,
                },
            },
        })

    async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
        await self.load_markets()
        url = self.urls['api']['ws']
        marketId = self.market_id(symbol)
        channel = 'market_' + marketId.lower() + '_depth_step0'
        request = {
            'event': 'sub',
            'params': {
                'channel': channel,
            },
        }
        messageHash = marketId + '_depth'
        return await self.watch(url, messageHash, self.extend(request, params), messageHash)

    def handle_order_book(self, client: Client, message):
        #
        #     {
        #         "channel": "market_btcusdt_depth_step0",
        #         "event_rep": "",
        #         "data": null,
        #         "ts": 1506584998239,
        #         "status": "ok",
        #         "tick": {
        #             "asks": [
        #                 [10000.19,0.93],
        #                 [10001.21,0.2],
        #                 [10002.22,0.34],
        #             ],
        #             "bids": [
        #                 [9999.53,0.93],
        #                 [9998.2,0.2],
        #                 [9997.19,0.21],
        #             ]
        #         }
        #     }
        #
        marketId = self.get_market_id_from_message(message)
        market = self.safe_market(marketId)
        symbol = market['symbol']
        tick = self.safe_dict(message, 'tick')
        timestamp = self.safe_number(message, 'ts')
        messageHash = marketId + '_depth'
        orderbook = self.parse_order_book(tick, symbol, timestamp, 'bids', 'asks')
        client.resolve(orderbook, messageHash)

    async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
        await self.load_markets()
        marketId = self.market_id(symbol)
        interval = self.safe_string(self.timeframes, timeframe)
        request = {
            'event': 'sub',
            'params': {
                'channel': 'market_' + marketId.lower() + '_kline_' + interval,
            },
        }
        url = self.urls['api']['ws']
        messageHash = marketId + '_ohlcv'
        return await self.watch(url, messageHash, self.extend(request, params), messageHash)

    def handle_ohlcv(self, client: Client, message):
        #
        #     {
        #         "channel": "market_$symbol_kline_1min",
        #         "event_rep": "",
        #         "data": null,
        #         "ts": 1506584998239,
        #         "status": "ok",
        #         "tick": {
        #             "amount": 1212.12211,
        #             "close":1221.11,
        #             "ds": "2024-05-13 14:39:23",
        #             "high":22322.22,
        #             "id": 1715583000,
        #             "low":2321.22,
        #             "open":2321.22,
        #             "tradeId": 0,
        #             "vol": 0.26292
        #         }
        #     }
        #
        marketId = self.get_market_id_from_message(message)
        tick = self.safe_dict(message, 'tick')
        timestamp = self.safe_number(tick, 'id') * 1e3
        fullData = self.extend(tick, {})
        fullData['idx'] = timestamp
        channel = self.safe_string(message, 'channel')
        arr = channel.split('_')
        interval = arr[3]
        timeframe = self.find_timeframe(interval, self.timeframes)
        ohlcvs = self.parse_ohlcvs([fullData], self.safe_market(marketId), timeframe)
        messageHash = marketId + '_ohlcv'
        client.resolve(ohlcvs, messageHash)

    async def watch_ticker(self, symbol: str, params={}) -> Ticker:
        await self.load_markets()
        marketId = self.market_id(symbol)
        request = {
            'event': 'sub',
            'params': {
                'channel': 'market_' + marketId.lower() + '_ticker',
            },
        }
        url = self.urls['api']['ws']
        messageHash = marketId + '_ticker'
        return await self.watch(url, messageHash, self.extend(request, params), messageHash)

    def handle_ticker(self, client: Client, message):
        #
        #     {
        #         "channel": "market_$symbol_ticker",
        #         "event_rep": "",
        #         "data": null,
        #         "ts": 1506584998239,
        #         "status": "ok",
        #         "tick": {
        #             "amount":123.1221,
        #             "vol":1212.12211,
        #             "open":2233.22,
        #             "close":1221.11,
        #             "high":22322.22,
        #             "low":2321.22,
        #             "rose":-0.2922,
        #         }
        #     }
        #
        marketId = self.get_market_id_from_message(message)
        timestamp = self.safe_number(message, 'ts')
        tick = self.safe_dict(message, 'tick')
        data = self.extend(tick, {})
        data['time'] = timestamp
        market = self.safe_market(marketId)
        ticker = self.parse_ticker(data, market)
        messageHash = marketId + '_ticker'
        client.resolve(ticker, messageHash)

    async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
        await self.load_markets()
        marketId = self.market_id(symbol)
        request = {
            'event': 'sub',
            'params': {
                'channel': 'market_' + marketId.lower() + '_trade_ticker',
            },
        }
        url = self.urls['api']['ws']
        messageHash = marketId + '_trades'
        return await self.watch(url, messageHash, self.extend(request, params), messageHash)

    def handle_trades(self, client: Client, message):
        #
        #     {
        #         "channel": "market_$symbol_trade_ticker",
        #         "ts": 1506584998239,
        #         "status": "ok",
        #         "data": null,
        #         "event_rep": "",
        #         "tick": {
        #             "data": [
        #                  {
        #                      "amount":"1212.12211",
        #                      "ds": "2024-05-13 14:39:23",
        #                      "price":"2233.22",
        #                      "side": "BUY",
        #                      "ts":1506584998239,
        #                      "vol":22322.22
        #                  }
        #              ],
        #          }
        #      }
        #
        marketId = self.get_market_id_from_message(message)
        market = self.safe_market(marketId)
        tick = self.safe_dict(message, 'tick')
        dataArr = self.safe_dict(tick, 'data')
        trades = []
        for i in range(0, len(dataArr)):
            data = dataArr[i]
            vol = self.safe_number(data, 'vol')
            ts = self.safe_number(data, 't')
            price = self.safe_number(data, 'price')
            side = self.safe_string(data, 'side').lower()
            trade = self.safe_trade({
                'info': message,
                'amount': vol,
                'datetime': self.iso8601(ts),
                'id': None,
                'order': None,
                'price': price,
                'timestamp': ts,
                'type': None,
                'side': side,
                'symbol': market['symbol'],
                'takerOrMaker': None,
                'cost': None,
                'fee': None,
            })
            trades.append(trade)
        messageHash = marketId + '_trades'
        client.resolve(trades, messageHash)

    def get_market_id_from_message(self, message) -> str:
        channel = self.safe_string(message, 'channel')
        arr = channel.split('_')
        return self.safe_string_upper(arr, 1)

    def handle_message(self, client: Client, message):
        if 'channel' in message:
            methods = {
                'depth': self.handle_order_book,
                'trade': self.handle_trades,
                'kline': self.handle_ohlcv,
                'ticker': self.handle_ticker,
            }
            messageType = self.get_channel_type(message)
            method = self.safe_value(methods, messageType)
            if method is not None:
                method(client, message)
        else:
            self.spawn(self.handle_heartbeat, client, message)

    async def handle_heartbeat(self, client: Client, message):
        ts = self.safe_number(message, 'ping')
        response = {
            'pong': ts,
        }
        await client.send(response)

    def get_channel_type(self, message) -> str:
        channel = self.safe_string(message, 'channel')
        arr = channel.split('_')
        return arr[2]
