from typing import List

from notecoin.huobi.constant import *
from notecoin.huobi.utils.print_mix_object import PrintBasic


class Trade:
    """
    The trade information with price and amount etc.

    :member
        price: The trading price in quote currency.
        amount: The trading volume in base currency.
        trade_id: The unique trade id of this trade.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        direction: The direction of the taker trade: 'buy' or 'sell'.
    """

    def __init__(self):
        self.price = 0.0
        self.amount = 0.0
        self.trade_id = 0
        self.ts = 0
        self.direction = ""

    def print_object(self, format_data=""):
        print(self.__dict__)


class TradeDetail:
    """
    The trade information with price and amount etc.

    :member
        price: The trading price in quote currency.
        amount: The trading volume in base currency.
        tradeId: The unique trade id of this trade.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        direction: The direction of the taker trade: 'buy' or 'sell'.
    """

    def __init__(self):
        self.price = 0.0
        self.amount = 0.0
        self.tradeId = 0
        self.ts = 0
        self.direction = ""

    def print_object(self, format_data=""):
        print(self.__dict__)


class TradeDetailEvent:
    """
    The trade received by subscription of trade.

    :member
        symbol: The symbol you subscribed.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        trade_list: The trade list. The content is Trade class.
    """

    def __init__(self):
        self.ch = ""
        self.id = 0
        self.ts = 0
        self.data: List[Trade] = []

    def print_object(self, format_data=""):
        print(self.__dict__)
        if len(self.data):
            for trade_detail in self.data:
                trade_detail.print_object()


class TradeDetailReq:
    """
    The trade received by subscription of trade.

    :member
        rep: The Channel you subscribed.
        trade_list: The trade list. The content is Trade class.
    """

    def __init__(self):
        self.rep = ""
        self.data = list()

    def print_object(self, format_data=""):
        print(self.__dict__)
        if len(self.data):
            for trade_detail in self.data:
                trade_detail.print_object()


class CandlestickEvent:
    """
    The candlestick/kline data received by subscription of candlestick/kline.

    :member
        ch: the topic you subscribed
        ts: the UNIX formatted timestamp generated by server in UTC.
        tick: the data of candlestick/kline.
    """

    def __init__(self):
        self.ch = ""
        self.ts = 0
        self.tick = Candlestick()

    def print_object(self, format_data=""):
        print(self.__dict__)
        if self.tick:
            self.tick.print_object()


class CandlestickReq:
    """
    The candlestick/kline data received by subscription of candlestick/kline.

    :member
        rep: the Channel or topic you subscribed.
        id: the UNIX formatted timestamp generated by server in UTC.
        data: the data of candlestick/kline.

    """

    def __init__(self):
        self.rep = ""
        self.id = 0
        self.data = list()

    def print_object(self, format_data=""):
        print(self.__dict__)
        if len(self.data):
            for row in self.data:
                row.print_object()


class Candlestick:
    """
    The candlestick/kline data.

    :member
        id : keep the original timestamp
        timestamp: The UNIX formatted timestamp in UTC.
        high: The high price.
        low: The low price.
        open: The opening price.
        close: The closing price.
        amount: The aggregated trading volume in USDT.
        count: The number of completed trades. it returns 0 when get ETF candlestick
        vol: The trading volume in base currency.

    """

    def __init__(self):
        self.id = 0
        #self.timestamp = 0
        self.high = 0.0
        self.low = 0.0
        self.open = 0.0
        self.close = 0.0
        self.amount = 0.0
        self.count = 0
        self.vol = 0.0  # self.volume = 0.0

    def print_object(self, format_data=""):
        print(self.__dict__)


class DepthEntry:
    """
    An depth entry consisting of price and amount.

    :member
        price: The price of the depth.
        amount: The amount of the depth.
    """

    def __init__(self):
        self.price = 0.0
        self.amount = 0.0

    @staticmethod
    def json_parse(data_array):
        entry = DepthEntry()
        entry.price = data_array[0]
        entry.amount = data_array[1]
        return entry

    def print_object(self, format_data=""):
        print(self.__dict__)


class LastTradeAndBestQuote:
    """
    The last trade and best bid/ask.

    :member
        last_trade_price: The last trade price.
        last_trade_amount: The last trade amount.
        ask_price: The best ask price.
        ask_amount: The best ask amount.
        bid_price: The best bid price.
        bid_amount: The best bid amount.

    """

    def __init__(self):
        self.last_trade_price = 0.0
        self.last_trade_amount = 0.0
        self.ask_price = 0.0
        self.ask_amount = 0.0
        self.bid_price = 0.0
        self.bid_amount = 0.0


class MarketDetailEvent:
    """
     The 24H trade statistics received by subscription of trade statistics.

     :member
         Channel: topic you subscribe, include symbol.
         timestamp: The UNIX formatted timestamp generated by server in UTC.
         trade_statistics: The trade statistics.
     """

    def __init__(self):
        self.ch = ""
        self.ts = 0
        self.tick = MarketDetail()

    def print_object(self, format_data=""):
        print(self.__dict__)


class MarketDetailMerged:
    """
    The best bid/ask consisting of price and amount.

    :member
        timestamp: The Unix formatted timestamp in UTC.
        bid_price: The best bid price.
        bid_amount: The best bid amount.
        ask_price: The best ask price.
        ask_amount: The best ask amount.

    """

    def __init__(self):
        self.amount = 0
        self.open = 0.0
        self.close = 0.0
        self.high = 0.0
        self.id = 0
        self.count = 0.0
        self.low = 0.0
        self.version = 0
        self.ask = []
        self.vol = 0.0
        self.bid = []

    def print_object(self, format_data=""):
        print(self.__dict__)


class MarketDetailReq:
    """
     The 24H trade statistics received by request of trade statistics only once.

     :member
         rep: The topic you subscribed.
         ts: The UNIX formatted timestamp generated by server in UTC.
         trade_statistics: The trade statistics.
     """

    def __init__(self):
        self.rep = 0
        self.ts = 0
        self.data = MarketDetail()

    def print_object(self, format_data=""):
        print(self.__dict__)


class MarketDetail:
    """
    The summary of trading in the market for the last 24 hours

    :member
        id: response ID
        open: The opening price of last 24 hours.
        close: The last price of last 24 hours.
        amount: The aggregated trading volume in USDT.
        high: The high price of last 24 hours.
        low: The low price of last 24 hours.
        count: The number of completed trades.
        volume: The trading volume in base currency of last 24 hours.
        version: inner data
    """

    def __init__(self):
        self.id = 0
        self.open = 0.0
        self.close = 0.0
        self.amount = 0.0
        self.high = 0.0
        self.low = 0.0
        self.count = 0
        self.vol = 0.0
        self.version = 0

    def print_object(self, format_data=""):
        print(self.__dict__)


class MarketTicker:
    """
    The ticker information.

    :member
        amount: The aggregated trading volume in last 24 hours (rotating 24h).
        count: The number of completed trades of last 24 hours (rotating 24h).
        open: The opening price of a nature day (Singapore time).
        close: The last price of a nature day (Singapore time).
        low: The low price of a nature day (Singapore time).
        high: The high price of a nature day (Singapore time).
        vol: The aggregated trading value in last 24 hours (rotating 24h).
        symbol: The trading symbol of this object, e.g. btcusdt, bccbtc.
        bid: Best bid price.
        bidSize: Best bid size.
        ask: Best ask price.
        askSize: Best ask size.
    """

    def __init__(self):
        self.amount = 0.0
        self.count = 0
        self.open = 0.0
        self.close = 0.0
        self.low = 0.0
        self.high = 0.0
        self.vol = 0.0
        self.symbol = ""
        self.bid = 0.0
        self.bidSize = 0.0
        self.ask = 0.0
        self.askSize = 0.0

    def print_object(self, format_data=""):
        print(self.__dict__)


class MbpFullEvent:
    """
    full price depth.

    :member
        ch: Topic of subscribed.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        data: The price depth.

    """

    def __init__(self):
        self.ch = ""
        self.ts = 0
        self.data = Mbp()

    @staticmethod
    def json_parse(json_data):
        mbp_event = MbpFullEvent()
        mbp_event.ts = json_data.get("ts")
        mbp_event.ch = json_data.get("ch")
        mbp = Mbp.json_parse(json_data.get("tick", {}))
        mbp_event.data = mbp
        return mbp_event

    def print_object(self, format_data=""):
        print(self.__dict__)
        self.data.print_object()


class MbpIncreaseEvent:
    """
    increasement of price depth.

    :member
        ch: Topic of subscribed.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        data: The price depth.

    """

    def __init__(self):
        self.ch = ""
        self.ts = 0
        self.data = Mbp()

    @staticmethod
    def json_parse(json_data):
        mbp_event = MbpIncreaseEvent()
        mbp_event.ts = json_data.get("ts")
        mbp_event.ch = json_data.get("ch")
        mbp = Mbp.json_parse(json_data.get("tick", {}))
        mbp_event.data = mbp
        return mbp_event

    def print_object(self, format_data=""):
        print(self.__dict__)
        self.data.print_object()


class MbpReq:
    """
    The market price depth.

    :member
        rep: request Topic
        id: The UNIX formatted timestamp generated by server in UTC.
        data: The price depth.
    """

    def __init__(self):
        self.rep = ""
        self.id = ""

        self.data = Mbp()

    @staticmethod
    def json_parse(data_json):
        mbp_event = MbpReq()
        mbp_event.id = data_json.get("id")
        mbp_event.rep = data_json.get("rep")
        data = data_json.get("data", {})
        mbp = Mbp.json_parse(data)
        mbp_event.data = mbp
        return mbp_event

    def print_object(self, format_data=""):
        print(self.__dict__)

        self.data.print_object()


class Mbp:
    """
    Increasement of price depth information.

    :member
        seqNum: current seqNum.
        prevSeqNum: previous seqNum.
        bids: The list of the bid depth. The content is DepthEntry class.
        asks: The list of the ask depth. The content is DepthEntry class.

    """

    def __init__(self):
        self.seqNum = 0
        self.prevSeqNum = 0
        self.bids = list()
        self.asks = list()

    @staticmethod
    def json_parse(json_data):
        mbp = Mbp()
        bid_list = list()
        mbp.seqNum = json_data.get("seqNum", 0)
        # prevSeqNum only for increased subscribe, request doesn't have this value
        mbp.prevSeqNum = json_data.get("prevSeqNum", 0)
        for item in json_data.get("bids", []):
            depth_entry = DepthEntry()
            depth_entry.price = item[0]
            depth_entry.amount = item[1]
            bid_list.append(depth_entry)
        ask_list = list()
        for item in json_data.get("asks", []):
            depth_entry = DepthEntry()
            depth_entry.price = item[0]
            depth_entry.amount = item[1]
            ask_list.append(depth_entry)
        mbp.bids = bid_list
        mbp.asks = ask_list

        return mbp

    def print_object(self, format_data=""):
        print(self.__dict__)
        for entry in self.bids:
            PrintBasic.print_basic(str(entry.price) + ", amount: " + str(entry.amount), format_data + "Bids price: ")

        for entry in self.asks:
            PrintBasic.print_basic(str(entry.price) + ", amount: " + str(entry.amount), format_data + "Asks price: ")


class PriceDepthBboEvent:
    """
    The price depth received by subscription of price depth.

    :member
        symbol: The symbol you subscribed.
        timestamp: The UNIX formatted timestamp generated by server in UTC.
        data: The price depth.

    """

    def __init__(self):
        self.ts = 0
        self.ch = ""
        self.tick = PriceDepthBbo()

    def print_object(self, format_data=""):
        print(self.__dict__)
        self.tick.print_object(format_data)


class PriceDepthBbo:
    """
    The price depth information.

    :member
        timestamp: The UNIX formatted timestamp in UTC.
        bid: the first bid near trade value.
        bidSize: the bid size.
        ask: The first ask near trade value.
        askSize: the ask size.
        quoteTime : quote time
        symbol : trade symbol


    """

    def __init__(self):
        self.seqId = 0
        self.ask = 0.0
        self.askSize = 0.0
        self.bid = 0.0
        self.bidSize = 0.0
        self.quoteTime = 0
        self.symbol = ""

    def print_object(self, format_data=""):
        print(self.__dict__)


class PriceDepthEvent:
    """
    The price depth information.

    :member
        ts: The UNIX formatted timestamp in UTC.
        version:
        bids: The list of the bid depth. The content is DepthEntry class.
        asks: The list of the ask depth. The content is DepthEntry class.

    """

    def __init__(self):
        self.ch = ""
        self.tick = PriceDepth()

    def print_object(self, format_data=""):
        print(self.__dict__)
        self.tick.print_object("\t")


class PriceDepthReq:
    """
    The price depth information.

    :member
        ts: The UNIX formatted timestamp in UTC.
        version:
        bids: The list of the bid depth. The content is DepthEntry class.
        asks: The list of the ask depth. The content is DepthEntry class.

    """

    def __init__(self):
        self.rep = ""
        self.data = PriceDepth()

    def print_object(self, format_data=""):
        print(self.__dict__)
        self.data.print_object("\t")


class PriceDepth:
    """
    The price depth information.

    :member
        ts: The UNIX formatted timestamp in UTC.
        version:
        bids: The list of the bid depth. The content is DepthEntry class.
        asks: The list of the ask depth. The content is DepthEntry class.

    """

    def __init__(self):
        self.ts = 0
        self.version = 0
        self.bids = list()
        self.asks = list()

    @staticmethod
    def json_parse(dict_data):
        price_depth_obj = PriceDepth()
        price_depth_obj.ts = dict_data.get("ts")
        price_depth_obj.version = dict_data.get("version")
        bid_list = list()
        bids_array = dict_data.get("bids", [])
        for item in bids_array:
            depth_entry = DepthEntry.json_parse(item)
            bid_list.append(depth_entry)
        ask_list = list()
        asks_array = dict_data.get("asks", [])
        for item in asks_array:
            depth_entry = DepthEntry.json_parse(item)
            ask_list.append(depth_entry)
        price_depth_obj.bids = bid_list
        price_depth_obj.asks = ask_list

        return price_depth_obj

    def print_object(self, format_data=""):
        print(self.__dict__)
        if len(self.bids):
            i = 0
            print(format_data, "---- Top " + str(len(self.bids)) + " bids ----")
            for entry in self.bids:
                i = i + 1
                print(format_data, str(i) + ": price: " + str(entry.price) + ", amount: " + str(entry.amount))
                # print()

        if len(self.asks):
            i = 0
            print(format_data, "---- Top " + str(len(self.asks)) + " asks ----")
            for entry in self.asks:
                i = i + 1
                print(format_data, str(i) + ": price: " + str(entry.price) + ", amount: " + str(entry.amount))
                # print()
                #
