# -*- 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

from ccxt.async_support.zb import zb

# -----------------------------------------------------------------------------

try:
    basestring  # Python 3
except NameError:
    basestring = str  # Python 2
import hashlib
from ccxt.base.errors import ExchangeError
from ccxt.base.errors import AuthenticationError
from ccxt.base.errors import PermissionDenied
from ccxt.base.errors import InvalidOrder
from ccxt.base.errors import ExchangeNotAvailable


class ceo(zb):

    def describe(self):
        return self.deep_extend(super(ceo, self).describe(), {
            'id': 'ceo',
            'name': 'CEO',
            'has': {
                'withdraw': False,
            },
            'exceptions': {
                '1001': ExchangeError,
                '1002': ExchangeError,
                '1003': AuthenticationError,
                '1004': ExchangeNotAvailable,
                '1005': ExchangeNotAvailable,
                '1006': PermissionDenied,
                '1007': ExchangeError,
                '1008': AuthenticationError,
            },
            'urls': {
                'api': 'https://api.ceo3.com/api',
                'www': 'https://www.ceoex.com',
                'doc': 'https://www.ceoex.com/apiDoc/con',
            },
            'api': {
                'public': {
                    'get': [
                        'market/markets',
                        'market/allTicker',
                        'market/ticker',
                        'market/entrust',
                        'market/trades',
                        'market/kline',
                    ],
                },
                'private': {
                    'get': [
                        'deal/accountInfo',
                        'deal/order',
                        'deal/cancelOrder',
                        'deal/getOrder',
                        'deal/getOrders',
                        'deal/getTrades',
                        'deal/getUserAddress',
                        'deal/getWithdrawAddress',
                        'deal/getWithdrawRecord',
                        'deal/getChargeRecord',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'taker': None,
                    'maker': None,
                },
                'funding': {
                    'withdraw': {},
                },
            },
            'commonCurrencies': {},
        })

    async def public_get_markets(self, params):
        response = await self.publicGetMarketMarkets()
        return response['data']

    async def private_get_get_account_info(self, params):
        response = await self.privateGetDealAccountInfo(params)
        response['result'] = response['data']
        return response

    async def fetch_markets(self, params={}):
        markets = await super(ceo, self).fetch_markets(params)
        for i in range(0, len(markets)):
            market = markets[i]
            info = self.safe_value(market, 'info')
            buyFee = self.safe_float(info, 'buyFee')
            sellFee = self.safe_float(info, 'sellFee')
            taker = None
            if (buyFee == sellFee) and (buyFee is not None):
                taker = buyFee / 100
            market['taker'] = taker
            market['maker'] = taker
        return markets

    def parse_ohlcv(self, ohlcv, market=None):
        return [
            self.safe_integer(ohlcv, 0),
            self.safe_float(ohlcv, 1),
            self.safe_float(ohlcv, 2),
            self.safe_float(ohlcv, 3),
            self.safe_float(ohlcv, 4),
            self.safe_float(ohlcv, 5),
        ]

    async def fetch_deposit_address(self, code, params={}):
        await self.load_markets()
        currency = self.currency(code)
        response = await self.privateGetDealGetUserAddress({
            'currency': currency['id'],
        })
        data = response['data']
        tag = None
        if data['memo']:
            tag = data['memo']
        return {
            'currency': code,
            'address': data['address'],
            'tag': tag,
            'info': response,
        }

    async def public_get_depth(self, params):
        response = await self.publicGetMarketEntrust(params)
        return {
            'bids': response['data']['b'],
            'asks': response['data']['s'],
        }

    async def fetch_tickers(self, symbols=None, params={}):
        await self.load_markets()
        response = await self.publicGetMarketAllTicker(params)
        result = {}
        ids = list(response['data'].keys())
        for i in range(0, len(ids)):
            market = self.marketsById[ids[i]]
            result[market['symbol']] = self.parse_ticker(response['data'][ids[i]], market)
        return result

    async def public_get_ticker(self, params):
        response = await self.publicGetMarketTicker(params)
        response['ticker'] = response['data']
        return response

    def parse_ticker(self, ticker, market=None):
        if ticker['sell'] == '0.00000000':
            ticker['sell'] = None
        return super(ceo, self).parse_ticker(ticker, market)

    async def public_get_kline(self, params):
        response = await self.publicGetMarketKline(self.extend(params))
        klines = self.safe_value(response['data'], 'data', [])
        data = []
        for i in range(0, len(klines)):
            kline = [
                klines[i][0],
                klines[i][2],
                klines[i][3],
                klines[i][4],
                klines[i][5],
                klines[i][1],
            ]
            data.append(kline)
        response['data'] = data
        return response

    def parse_trade(self, trade, market=None):
        timestamp = trade['time'] * 1000
        side = 'buy' if (trade['type'] == 1) else 'sell'
        return {
            'info': trade,
            'id': None,
            'timestamp': timestamp,
            'datetime': self.iso8601(timestamp),
            'symbol': market['symbol'],
            'type': None,
            'side': side,
            'price': self.safe_float(trade, 'price'),
            'amount': self.safe_float(trade, 'amount'),
        }

    async def public_get_trades(self, params):
        response = await self.publicGetMarketTrades(params)
        return response['data']

    async def create_order(self, symbol, type, side, amount, price=None, params={}):
        if type != 'limit':
            raise InvalidOrder(self.id + ' allows limit orders only')
        await self.load_markets()
        order = {
            'price': self.price_to_precision(symbol, price),
            'amount': self.amount_to_precision(symbol, amount),
            'tradeType': '1' if (side == 'buy') else '2',
            'currency': self.market_id(symbol),
        }
        response = await self.privateGetDealOrder(self.extend(order, params))
        return {
            'info': response['data'],
            'id': response['data']['orderId'],
        }

    async def private_get_cancel_order(self, params):
        return await self.privateGetDealCancelOrder(params)

    async def private_get_get_order(self, params):
        response = await self.privateGetDealGetOrder(params)
        return response['data']

    async def private_get_get_orders_ignore_trade_type(self, params):
        return await self.private_get_get_orders_new(params)

    async def private_get_get_unfinished_orders_ignore_trade_type(self, params):
        return await self.private_get_get_orders_new(self.deep_extend({'tradeStatus': 1}, params))

    async def private_get_get_orders_new(self, params):
        response = await self.privateGetDealGetOrders(params)
        return response['data']

    def parse_order(self, order, market=None):
        createDateField = self.getCreateDateField()
        if createDateField in order:
            order[createDateField] = order[createDateField] * 1000
        createTimeField = self.get_create_time_field()
        if createTimeField in order:
            order[createDateField] = order[createTimeField] * 1000
        return super(ceo, self).parse_order(order, market)

    def get_create_time_field(self):
        return 'trade_time'

    def parse_order_status(self, status):
        statuses = {
            '0': 'open',
            '1': 'closed',
            '2': 'canceled',
            '3': 'open',
        }
        if status in statuses:
            return statuses[status]
        return status

    def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
        url = self.urls['api']
        if api == 'public':
            url += '/' + path
            if params:
                url += '?' + self.urlencode(params)
        else:
            query = self.keysort(self.extend({
                'method': path.split('/')[1],
                'accesskey': self.apiKey,
                'reqTime': str(self.nonce()),
            }, params))
            query = self.rawencode(query)
            signature = self.hmac(query, self.secret, hashlib.md5)
            url += '/' + path + '?' + query + '&sign=' + signature
        return {'url': url, 'method': method, 'body': body, 'headers': headers}

    def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
        if not isinstance(body, basestring):
            return
        if len(body) < 2:
            return
        if body[0] == '{':
            feedback = self.id + ' ' + self.json(response)
            if 'code' in response:
                code = self.safe_string(response, 'code')
                if code in self.exceptions:
                    ExceptionClass = self.exceptions[code]
                    raise ExceptionClass(feedback)
                elif code != '1000':
                    raise ExchangeError(feedback)
            result = self.safe_value(response, 'data')
            if result is not None:
                if not result:
                    message = self.safe_string(response, 'message')
                    if message == '撤销成功':
                        return
                    raise ExchangeError(feedback)
