# -*- 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.base.exchange import Exchange

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

try:
    basestring  # Python 3
except NameError:
    basestring = str  # Python 2
import math
from ccxt.base.errors import ExchangeError
from ccxt.base.errors import AuthenticationError
from ccxt.base.errors import InsufficientFunds
from ccxt.base.errors import OrderNotFound
from ccxt.base.errors import DDoSProtection
from ccxt.base.decimal_to_precision import TICK_SIZE


class bitforexfu(Exchange):

    def describe(self):
        return self.deep_extend(super(bitforexfu, self).describe(), {
            'id': 'bitforexfu',
            'name': 'Bitforex Futures',
            'countries': ['CN'],
            # 'version': 'v1',
            'has': {
                'cancelOrder': False,
                'createLimitOrder': False,
                'createMarketOrder': False,
                'createOrder': False,
                'editOrder': False,
                'fetchBalance': False,
                'fetchL2OrderBook': False,
                'fetchMarkets': True,
                'fetchOHLCV': True,
                'fetchOrderBook': False,
                'fetchStatus': 'emulated',
                'fetchTicker': False,
                'fetchTrades': False,
                'privateAPI': False,
                'publicAPI': False,
            },
            'timeframes': {
                '1m': '1min',
                '5m': '5min',
                '15m': '15min',
                '30m': '30min',
                '1h': '1hour',
                '2h': '2hour',
                '4h': '4hour',
                '12h': '12hour',
                '1d': '1day',
                '1w': '1week',
                '1M': '1month',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/44310033-69e9e600-a3d8-11e8-873d-54d74d1bc4e4.jpg',
                'api': {
                    'public': 'https://www.bitforex.com/contract',
                    'private': 'https://www.bitforex.com/contract',
                },
                'www': 'https://www.bitforex.com',
                'doc': 'https://github.com/githubdev2020/API_Doc_en/wiki',
                'fees': 'https://help.bitforex.com/en_us/?cat=13',
                'referral': None,
            },
            'api': {
                'public': {
                    'get': [
                        'swap/contract/listAll',
                        'mkapi/depth',
                        'mkapi/kline',
                    ],
                },
                'private': {
                    'post': [
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': False,
                    'percentage': True,
                    'maker': 0.04 / 100,
                    'taker': 0.06 / 100,
                },
                'funding': {
                    'tierBased': False,
                    'percentage': True,
                    'deposit': {},
					'withdraw': {},
                },
            },
            'exceptions': {
                '4004': OrderNotFound,
                '1013': AuthenticationError,
                '1016': AuthenticationError,
                '3002': InsufficientFunds,
                '10204': DDoSProtection,
            },
            'precisionMode': TICK_SIZE,
        })

    async def fetch_markets(self, params={}):
        response = await self.publicGetSwapContractListAll(params)
        #  {
        #    "data": [
        #      {
        #          id  10002
        #          symbol  "swap-usd-btc"
        #          baseSymbol  "BTC"
        #          quoteSymbol "USD"
        #          initMargins 0.01
        #          maintenanceMargins  0.005
        #          fundPreminumSymbol  "BTC"
        #          unitQuantity    1
        #          beginTime   1560648043415
        #          leverageLevel   100
        #          minOrderPrice   1e-8
        #          maxOrderPrice   1000000
        #          minOrderVolume  1
        #          maxOrderVolume  2000000
        #          maxUserVolume   5500000
        #          pricePrecision  2
        #          basePrecision   8
        #          openBuyLimitRate    0.01
        #          openSellLimitRate   0.01
        #          openBuyLimitRateMax 0.02
        #          openSellLimitRateMax    1000
        #          openBuyLimitRateMin 1
        #          openSellLimitRateMin    0.02
        #          feeRateMaker    0.0004
        #          feeRateTaker    0.0006
        #          fundPeriod  8
        #          isAutoReduce    True
        #          contractType    1
        #          dealNum 3
        #          deepJoinNum "2"
        #          minChangePrice  0.5
        #          alias   "BTC/USD"
        #          limitQuota  200000
        #          increaseLimitQuota  null
        #          status  "0"
        #          ctime   1560561643416
        #          mtime   1568855964408
        #          depthConfig "1,2,5,10,20"
        #          priceOrderPrecision 1
        #          baseShowPrecision   8
        #          depthOffset 10
        #          floatY  0.005
        #          riskRate    1
        #          outStatus   "0"
        #          inStatus    "0"
        #          currentPricePrecision   2
        #      }
        #    ]
        #  }
        data = response['data']
        result = []
        for i in range(0, len(data)):
            market = data[i]
            id = self.safe_string(market, 'symbol')
            symbolParts = id.split('-')
            baseId = symbolParts[2]
            quoteId = symbolParts[1]
            base = self.safe_currency_code(baseId)
            quote = self.safe_currency_code(quoteId)
            symbol = base + '/' + quote
            active = True
            maker = self.safe_float(market, 'feeRateMaker')
            taker = self.safe_float(market, 'feeRateTaker')
            pricePrecision = self.safe_integer(market, 'priceOrderPrecision')
            precision = {
                'amount': self.safe_integer(market, 'unitQuantity'),
                'price': math.pow(10, -pricePrecision),  # TICK_SIZE
            }
            limits = {
                'amount': {
                    'min': self.safe_float(market, 'minOrderVolume'),
                    'max': self.safe_float(market, 'maxOrderVolume'),
                },
                'price': {
                    'min': self.safeFloat( market, 'minOrderPrice'),
                    'max': self.safeFloat( market, 'maxOrderPrice'),
                },
                'cost': {
                    'min': None,
                    'max': None,
                },
            }
            result.append({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'active': active,
                'precision': precision,
                'limits': limits,
                'maker': maker,
                'taker': taker,
                'type': 'swap',
                'spot': False,
                'swap': True,
                'future': False,
                'info': market,
            })
        return result

    def parse_ohlcv(self, ohlcv, market=None, timeframe='1m', since=None, limit=None):
		# quoteVolume = self.safe_float(ohlcv, 'vol')
        return [
            self.safe_integer(ohlcv, 'time'),
            self.safe_float(ohlcv, 'open'),
            self.safe_float(ohlcv, 'high'),
            self.safe_float(ohlcv, 'low'),
            self.safe_float(ohlcv, 'close'),
            None,
        ]

    async def fetch_ohlcv(self, symbol, timeframe='1m', since=None, limit=None, params={}):
        await self.load_markets()
        market = self.market(symbol)
		# size is required, max 600
        size = 600
        if limit is not None:
            size = limit
        request = {
            'businessType': market['id'],
            'kType': self.timeframes[timeframe],
			'size': size,
        }
        response = await self.publicGetMkapiKline(self.extend(request, params))
        ohlcvs = self.safe_value(response, 'data', [])
        return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)

    def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
        url = self.urls['api'][api] + '/' + self.implode_params(path, params)
        query = self.omit(params, self.extract_params(path))
        if api == 'public':
            if query:
                url += '?' + self.urlencode(query)
        else:
            self.check_required_credentials()
            payload = self.urlencode({'accessKey': self.apiKey})
            query['nonce'] = self.milliseconds()
            if query:
                payload += '&' + self.urlencode(self.keysort(query))
            # message = '/' + 'api/' + self.version + '/' + path + '?' + payload
            message = '/' + path + '?' + payload
            signature = self.hmac(self.encode(message), self.encode(self.secret))
            body = payload + '&signData=' + signature
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            }
        return {'url': url, 'method': method, 'body': body, 'headers': headers}

    def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
        if not isinstance(body, basestring):
            return  # fallback to default error handler
        if (body[0] == '{') or (body[0] == '['):
            feedback = self.id + ' ' + body
            success = self.safe_value(response, 'success')
            if success is not None:
                if not success:
                    code = self.safe_string(response, 'code')
                    self.throw_exactly_matched_exception(self.exceptions, code, feedback)
                    raise ExchangeError(feedback)
