#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'HaiFeng'
__mtime__ = '2016/9/23'
"""

import threading
import platform
import os

from .structs import InfoField, Tick
from .ctp_quote import Quote
from .ctp_struct import CThostFtdcRspUserLoginField, CThostFtdcRspInfoField, CThostFtdcDepthMarketDataField, CThostFtdcSpecificInstrumentField


class CtpQuote(object):
    """"""

    def __init__(self):
        self.q = Quote(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'lib', 'ctp_quote.' + ('dll' if 'Windows' in platform.system() else 'so')))
        self.inst_tick = {}
        self.logined = False

    def ReqConnect(self, pAddress: str):
        """
        连接行情前置
            :param self: 
            :param pAddress:str: 
        """
        self.q.CreateApi()
        spi = self.q.CreateSpi()
        self.q.RegisterSpi(spi)

        self.q.OnFrontConnected = self._OnFrontConnected
        self.q.OnFrontDisconnected = self._OnFrontDisConnected
        self.q.OnRspUserLogin = self._OnRspUserLogin
        self.q.OnRtnDepthMarketData = self._OnRtnDepthMarketData
        self.q.OnRspSubMarketData = self._OnRspSubMarketData

        self.q.RegCB()

        self.q.RegisterFront(pAddress)
        self.q.Init()

    def ReqUserLogin(self, user: str, pwd: str, broker: str):
        """
        登录
            :param self:
            :param user:str:
            :param pwd:str:
            :param broker:str:
        """
        self.q.ReqUserLogin(BrokerID=broker, UserID=user, Password=pwd)

    def ReqSubscribeMarketData(self, pInstrument: str):
        """
        订阅合约行情
            :param self:
            :param pInstrument:str:
        """
        self.q.SubscribeMarketData(pInstrument)

    def ReqUserLogout(self):
        """
        退出接口
            :param self: 
        """
        self.q.Release()
        threading.Thread(target=self.OnDisConnected, args=(self, 0)).start()

    def _OnFrontConnected(self):
        """"""
        threading.Thread(target=self.OnConnected, args=(self,)).start()

    def _OnFrontDisConnected(self, reason: int):
        """"""
        # 确保隔夜或重新登录时的第1个tick不被发送到客户端
        self.inst_tick.clear()
        threading.Thread(target=self.OnDisConnected, args=(self, reason)).start()

    def _OnRspUserLogin(self, pRspUserLogin: CThostFtdcRspUserLoginField, pRspInfo: CThostFtdcRspInfoField, nRequestID: int, bIsLast: bool):
        """"""
        info = InfoField()
        info.ErrorID = pRspInfo.getErrorID()
        info.ErrorMsg = pRspInfo.getErrorMsg()
        self.logined = True
        threading.Thread(target=self.OnUserLogin, args=(self, info)).start()

    def _OnRspSubMarketData(self, pSpecificInstrument: CThostFtdcSpecificInstrumentField, pRspInfo: CThostFtdcRspInfoField, nRequestID: int, bIsLast: bool):
        pass

    def _OnRtnDepthMarketData(self, pDepthMarketData: CThostFtdcDepthMarketDataField):
        """"""
        tick: Tick = None
        # 这个逻辑交由应用端处理更合理 ==> 第一个tick不送给客户端(以处理隔夜早盘时收到夜盘的数据的问题)
        inst = pDepthMarketData.getInstrumentID()
        if inst not in self.inst_tick:
            tick = Tick()
            self.inst_tick[inst] = tick
        else:
            tick = self.inst_tick[inst]

        tick.AskPrice = pDepthMarketData.getAskPrice1()
        tick.AskVolume = pDepthMarketData.getAskVolume1()
        tick.AveragePrice = pDepthMarketData.getAveragePrice()
        tick.BidPrice = pDepthMarketData.getBidPrice1()
        tick.BidVolume = pDepthMarketData.getBidVolume1()
        tick.Instrument = pDepthMarketData.getInstrumentID()
        tick.LastPrice = pDepthMarketData.getLastPrice()
        tick.OpenInterest = pDepthMarketData.getOpenInterest()
        tick.Volume = pDepthMarketData.getVolume()

        # 用tradingday替代Actionday不可取
        # day = pDepthMarketData.getTradingDay()
        # str = day + ' ' + pDepthMarketData.getUpdateTime()
        # if day is None or day == ' ':
        #     str = time.strftime('%Y%m%d %H:%M:%S', time.localtime())
        # tick.UpdateTime = str  # time.strptime(str, '%Y%m%d %H:%M:%S')

        tick.UpdateTime = pDepthMarketData.getUpdateTime()
        tick.UpdateMillisec = pDepthMarketData.getUpdateMillisec()
        tick.UpperLimitPrice = pDepthMarketData.getUpperLimitPrice()
        tick.LowerLimitPrice = pDepthMarketData.getLowerLimitPrice()
        tick.PreOpenInterest = pDepthMarketData.getPreOpenInterest()

        # 用线程会导入多数据入库时报错
        # threading.Thread(target=self.OnTick, (self, tick))
        self.OnTick(self, tick)

    def OnDisConnected(self, obj, error: int):
        """"""
        print('disconnected: ' + str(error))

    def OnConnected(self, obj):
        """"""
        print('connected')

    def OnUserLogin(self, obj, info: InfoField):
        """"""
        print(info)

    def OnTick(self, obj, f: Tick):
        """"""
        print(f.__dict__)


def connected(obj):
    print('connected')
    obj.ReqUserLogin('008105', '1', '9999')


def logged(obj, info):
    print(info)


def main():
    q = CtpQuote()
    q.OnConnected = connected
    q.OnUserLogin = logged
    q.ReqConnect('tcp://180.168.146.187:10010')

    input()
    q.Release()
    input()


if __name__ == '__main__':
    main()
