import json
import zmq
import zmq.asyncio
from time import time
from copy import copy

from cryptofeed.defines import L2_BOOK, BID, ASK


class BookTopZMQ(BackendQueue):
    def __init__(self, host='127.0.0.1', port=6000, **kwargs):
        print('callback initiated')
        url = "tcp://{}:{}".format(host, port)
        ctx = zmq.asyncio.Context.instance()
        self.con = ctx.socket(zmq.PUB)
        self.con.connect(url)
        self.key = key if key else self.default_key
        self.numeric_type = numeric_type
        self.dynamic_key = dynamic_key

    async def write(self, feed: str, symbol: str, timestamp: float, recceipt_timestamp: float, data: dict):
        dic = self.parse_top(feed, )

    '''
    async def __call__(self, *, feed, pair, book, timestamp, receipt_timestamp):
        dic = self.parse_top(feed, pair, book, timestamp, receipt_timestamp)
        rticker = []
        for k in ['ask', 'bid', 'ask_volume', 'bid_volume']:
            rticker.append(dic[k])
        old_ticker = copy(self.ticker)
        if self.ticker != rticker:
            self.ticker = rticker
            flags = []
            if old_ticker != None:
                if rticker[0] != old_ticker[0]:
                    flags.append('ask')
                if rticker[1] != old_ticker[1]:
                    flags.append('bid')
            dic['flags'] = flags
            await self.con.send_string(json.dumps(dic))
            #print('update sent')
        else:
            #print('does not update top of book')
            pass
    '''
    def parse_top(self, feed, pair, book, timestamp, receipt_timestamp):
        ask, ask_volume = next(iter(book[ASK].items()))
        bid, bid_volume = book[BID].items()[-1]
        out_dic = {
            'type': 'ticker',
            'feed': feed,
            'pair': pair,
            'timestamp': timestamp,
            'time_received': time(),
            'ask': str(ask),
            'ask_volume': str(ask_volume),
            'ask_comment': '',
            'bid': str(bid),
            'bid_volume': str(bid_volume),
            'bid_comment': ''
        }
        #pprint(out_dic)
        return out_dic

class MarketTopZMQ():
    def __init__(self, host='127.0.0.1', port=6000, **kwargs):
        print('callback initiated')
        url = "tcp://{}:{}".format(host, port)
        ctx = zmq.asyncio.Context.instance()
        self.con = ctx.socket(zmq.PUB)
        self.con.connect(url)
        self.ticker = None

    async def __call__(self, *, feed, pair, market_book, timestamp, receipt_timestamp):
        dic = self.parse_top(feed, pair,  market_book, timestamp, receipt_timestamp)
        rticker = []
        for k in ['ask', 'bid', 'ask_volume', 'bid_volume', 'ask_comment', 'bid_comment']:
            rticker.append(dic.get(k, None))
        old_ticker  = copy(self.ticker)
        if self.ticker != rticker:
            self.ticker = rticker
            flags = []
            if old_ticker != None:
                if rticker[0] != old_ticker[0]:
                    flags.append('ask')
                if rticker[1] != old_ticker[1]:
                    flags.append('bid')
            dic['flags'] = flags
            await self.con.send_string(json.dumps(dic))
            #print('update sent')
        else:
            #print('does not update top of book')
            pass

    def parse_top(self, feed, pair, market_book, timestamp, receipt_timestamp):
        ask, ask_volume,ask_ename = market_book[ASK][0]
        bid, bid_volume, bid_ename = market_book[BID][0]
        out_dic = {
            'type': 'ticker',
            'feed': feed,
            'pair': pair,
            'timestamp': timestamp,
            'time_received': receipt_timestamp,
            'ask': str(ask),
            'ask_volume': str(ask_volume),
            'ask_comment': ask_ename,
            'bid': str(bid),
            'bid_volume': str(bid_volume),
            'bid_comment': bid_ename
        }
        return out_dic
