#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : HaiFeng
# @Email   : 24918700@qq.com
# @Time    : 2022/09/11


import os
import platform
import copy

from ctypes import *
from .structs import *


class Quote:

    def __init__(self):
        dllpath = os.path.join(os.path.abspath(os.path.dirname(__file__)), "lib64")
        absolute_dllfile_path = os.path.join(dllpath, 'ctp_quote.dll' if 'Windows' in platform.system() else 'libctp_quote.so')
        if not os.path.exists(absolute_dllfile_path):
            print('缺少DLL接口文件')
            return

        # make log dir for api log
        logdir = os.path.join(os.getcwd(), 'log')
        if not os.path.exists(logdir):
            os.mkdir(logdir)
 
        dlldir = os.path.split(absolute_dllfile_path)[0]
        # change work directory
        cur_path = os.getcwd()
        os.chdir(dlldir)

        self.h = CDLL(absolute_dllfile_path)

        self.h.qCreateApi.argtypes = []
        self.h.qCreateApi.restype = c_void_p

        self.h.qCreateSpi.argtypes = []
        self.h.qCreateSpi.restype = c_void_p

        self.api = None
        self.spi = None

        #################### 请求函数 #######################
        # 创建MdApi
        self.h.qRelease.argtypes = [c_void_p]
        self.h.qRelease.restype = c_void_p
        # 初始化
        self.h.qInit.argtypes = [c_void_p]
        self.h.qInit.restype = c_void_p
        # 等待接口线程结束运行
        self.h.qJoin.argtypes = [c_void_p]
        self.h.qJoin.restype = c_void_p
        # 注册前置机网络地址
        self.h.qRegisterFront.argtypes = [c_void_p, c_void_p]
        self.h.qRegisterFront.restype = c_void_p
        # @remark RegisterNameServer优先于RegisterFront
        self.h.qRegisterNameServer.argtypes = [c_void_p, c_void_p]
        self.h.qRegisterNameServer.restype = c_void_p
        # 注册名字服务器用户信息
        self.h.qRegisterFensUserInfo.argtypes = [c_void_p, c_void_p]
        self.h.qRegisterFensUserInfo.restype = c_void_p
        # 注册回调接口
        self.h.qRegisterSpi.argtypes = [c_void_p, c_void_p]
        self.h.qRegisterSpi.restype = c_void_p
        # 订阅行情。
        self.h.qSubscribeMarketData.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qSubscribeMarketData.restype = c_void_p
        # 退订行情。
        self.h.qUnSubscribeMarketData.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qUnSubscribeMarketData.restype = c_void_p
        # 订阅询价。
        self.h.qSubscribeForQuoteRsp.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qSubscribeForQuoteRsp.restype = c_void_p
        # 退订询价。
        self.h.qUnSubscribeForQuoteRsp.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qUnSubscribeForQuoteRsp.restype = c_void_p
        # 用户登录请求
        self.h.qReqUserLogin.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qReqUserLogin.restype = c_void_p
        # 登出请求
        self.h.qReqUserLogout.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qReqUserLogout.restype = c_void_p
        # 请求查询组播合约
        self.h.qReqQryMulticastInstrument.argtypes = [c_void_p, c_void_p, c_int32]
        self.h.qReqQryMulticastInstrument.restype = c_void_p
        
        os.chdir(cur_path)

    def CreateApi(self):
        self.api = self.h.qCreateApi()
        return self.api

    def CreateSpi(self):
        self.spi = self.h.qCreateSpi()
        #################### 响应函数 #########################
        # 当客户端与交易后台建立起通信连接时（还未登录前），该方法被调用。
        self.h.qSetOnFrontConnected.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnFrontConnected.restype = None
        self.evOnFrontConnected = CFUNCTYPE(None)(self.__OnFrontConnected)
        self.h.qSetOnFrontConnected(self.spi, self.evOnFrontConnected)
        # 当客户端与交易后台通信连接断开时，该方法被调用。当发生这个情况后，API会自动重新连接，客户端可不做处理。
        self.h.qSetOnFrontDisconnected.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnFrontDisconnected.restype = None
        self.evOnFrontDisconnected = CFUNCTYPE(None, c_int32)(self.__OnFrontDisconnected)
        self.h.qSetOnFrontDisconnected(self.spi, self.evOnFrontDisconnected)
        # 心跳超时警告。当长时间未收到报文时，该方法被调用。
        self.h.qSetOnHeartBeatWarning.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnHeartBeatWarning.restype = None
        self.evOnHeartBeatWarning = CFUNCTYPE(None, c_int32)(self.__OnHeartBeatWarning)
        self.h.qSetOnHeartBeatWarning(self.spi, self.evOnHeartBeatWarning)
        # 登录请求响应
        self.h.qSetOnRspUserLogin.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspUserLogin.restype = None
        self.evOnRspUserLogin = CFUNCTYPE(None, POINTER(CThostFtdcRspUserLoginField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspUserLogin)
        self.h.qSetOnRspUserLogin(self.spi, self.evOnRspUserLogin)
        # 登出请求响应
        self.h.qSetOnRspUserLogout.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspUserLogout.restype = None
        self.evOnRspUserLogout = CFUNCTYPE(None, POINTER(CThostFtdcUserLogoutField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspUserLogout)
        self.h.qSetOnRspUserLogout(self.spi, self.evOnRspUserLogout)
        # 请求查询组播合约响应
        self.h.qSetOnRspQryMulticastInstrument.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspQryMulticastInstrument.restype = None
        self.evOnRspQryMulticastInstrument = CFUNCTYPE(None, POINTER(CThostFtdcMulticastInstrumentField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspQryMulticastInstrument)
        self.h.qSetOnRspQryMulticastInstrument(self.spi, self.evOnRspQryMulticastInstrument)
        # 错误应答
        self.h.qSetOnRspError.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspError.restype = None
        self.evOnRspError = CFUNCTYPE(None, POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspError)
        self.h.qSetOnRspError(self.spi, self.evOnRspError)
        # 订阅行情应答
        self.h.qSetOnRspSubMarketData.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspSubMarketData.restype = None
        self.evOnRspSubMarketData = CFUNCTYPE(None, POINTER(CThostFtdcSpecificInstrumentField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspSubMarketData)
        self.h.qSetOnRspSubMarketData(self.spi, self.evOnRspSubMarketData)
        # 取消订阅行情应答
        self.h.qSetOnRspUnSubMarketData.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspUnSubMarketData.restype = None
        self.evOnRspUnSubMarketData = CFUNCTYPE(None, POINTER(CThostFtdcSpecificInstrumentField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspUnSubMarketData)
        self.h.qSetOnRspUnSubMarketData(self.spi, self.evOnRspUnSubMarketData)
        # 订阅询价应答
        self.h.qSetOnRspSubForQuoteRsp.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspSubForQuoteRsp.restype = None
        self.evOnRspSubForQuoteRsp = CFUNCTYPE(None, POINTER(CThostFtdcSpecificInstrumentField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspSubForQuoteRsp)
        self.h.qSetOnRspSubForQuoteRsp(self.spi, self.evOnRspSubForQuoteRsp)
        # 取消订阅询价应答
        self.h.qSetOnRspUnSubForQuoteRsp.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRspUnSubForQuoteRsp.restype = None
        self.evOnRspUnSubForQuoteRsp = CFUNCTYPE(None, POINTER(CThostFtdcSpecificInstrumentField), POINTER(CThostFtdcRspInfoField), c_int32, c_bool)(self.__OnRspUnSubForQuoteRsp)
        self.h.qSetOnRspUnSubForQuoteRsp(self.spi, self.evOnRspUnSubForQuoteRsp)
        # 深度行情通知
        self.h.qSetOnRtnDepthMarketData.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRtnDepthMarketData.restype = None
        self.evOnRtnDepthMarketData = CFUNCTYPE(None, POINTER(CThostFtdcDepthMarketDataField))(self.__OnRtnDepthMarketData)
        self.h.qSetOnRtnDepthMarketData(self.spi, self.evOnRtnDepthMarketData)
        # 询价通知
        self.h.qSetOnRtnForQuoteRsp.argtypes = [c_void_p, c_void_p]
        self.h.qSetOnRtnForQuoteRsp.restype = None
        self.evOnRtnForQuoteRsp = CFUNCTYPE(None, POINTER(CThostFtdcForQuoteRspField))(self.__OnRtnForQuoteRsp)
        self.h.qSetOnRtnForQuoteRsp(self.spi, self.evOnRtnForQuoteRsp)
        
        return self.spi

    #################### 请求函数 #######################
    
    def Release(self):
        """ 创建MdApi """
        self.h.qRelease(self.api)
    
    def Init(self):
        """ 初始化 """
        self.h.qInit(self.api)
    
    def Join(self):
        """ 等待接口线程结束运行 """
        self.h.qJoin(self.api)
    
    def RegisterFront(self, pszFrontAddress:str):
        """ 注册前置机网络地址 """
        self.h.qRegisterFront(self.api, bytes(pszFrontAddress, encoding='ascii'))
    
    def RegisterNameServer(self, pszNsAddress:str):
        """ @remark RegisterNameServer优先于RegisterFront """
        self.h.qRegisterNameServer(self.api, bytes(pszNsAddress, encoding='ascii'))
    
    def RegisterFensUserInfo(self,  pFensUserInfo:CThostFtdcFensUserInfoField):
        """ 注册名字服务器用户信息 """
        self.h.qRegisterFensUserInfo(self.api, byref( pFensUserInfo))
    
    def RegisterSpi(self, pSpi:c_void_p):
        """ 注册回调接口 """
        self.h.qRegisterSpi(self.api, pSpi)
    
    def SubscribeMarketData(self, ppInstrumentID:str, nCount:int):
        """ 订阅行情。 """
        self.h.qSubscribeMarketData(self.api, ppInstrumentID, nCount)
    
    def UnSubscribeMarketData(self, ppInstrumentID:str, nCount:int):
        """ 退订行情。 """
        self.h.qUnSubscribeMarketData(self.api, ppInstrumentID, nCount)
    
    def SubscribeForQuoteRsp(self, ppInstrumentID:str, nCount:int):
        """ 订阅询价。 """
        self.h.qSubscribeForQuoteRsp(self.api, ppInstrumentID, nCount)
    
    def UnSubscribeForQuoteRsp(self, ppInstrumentID:str, nCount:int):
        """ 退订询价。 """
        self.h.qUnSubscribeForQuoteRsp(self.api, ppInstrumentID, nCount)
    
    def ReqUserLogin(self, pReqUserLoginField:CThostFtdcReqUserLoginField, nRequestID:int):
        """ 用户登录请求 """
        self.h.qReqUserLogin(self.api, byref(pReqUserLoginField), nRequestID)
    
    def ReqUserLogout(self, pUserLogout:CThostFtdcUserLogoutField, nRequestID:int):
        """ 登出请求 """
        self.h.qReqUserLogout(self.api, byref(pUserLogout), nRequestID)
    
    def ReqQryMulticastInstrument(self, pQryMulticastInstrument:CThostFtdcQryMulticastInstrumentField, nRequestID:int):
        """ 请求查询组播合约 """
        self.h.qReqQryMulticastInstrument(self.api, byref(pQryMulticastInstrument), nRequestID)
    
    #################### 响应函数 #########################
    
    def __OnFrontConnected(self):
        self.OnFrontConnected()
    def OnFrontConnected(self):
        """ 当客户端与交易后台建立起通信连接时（还未登录前），该方法被调用。 """
        print('===OnFrontConnected===:')
    
    def __OnFrontDisconnected(self, nReason:int):
        self.OnFrontDisconnected(nReason)
    def OnFrontDisconnected(self, nReason:int):
        """ 当客户端与交易后台通信连接断开时，该方法被调用。当发生这个情况后，API会自动重新连接，客户端可不做处理。 """
        print('===OnFrontDisconnected===:nReason:int')
    
    def __OnHeartBeatWarning(self, nTimeLapse:int):
        self.OnHeartBeatWarning(nTimeLapse)
    def OnHeartBeatWarning(self, nTimeLapse:int):
        """ 心跳超时警告。当长时间未收到报文时，该方法被调用。 """
        print('===OnHeartBeatWarning===:nTimeLapse:int')
    
    def __OnRspUserLogin(self, pRspUserLogin:CThostFtdcRspUserLoginField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspUserLogin(copy.deepcopy(POINTER(CThostFtdcRspUserLoginField).from_param(pRspUserLogin).contents) if pRspUserLogin else CThostFtdcRspUserLoginField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspUserLogin(self, pRspUserLogin:CThostFtdcRspUserLoginField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 登录请求响应 """
        print('===OnRspUserLogin===:pRspUserLogin:CThostFtdcRspUserLoginField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspUserLogout(self, pUserLogout:CThostFtdcUserLogoutField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspUserLogout(copy.deepcopy(POINTER(CThostFtdcUserLogoutField).from_param(pUserLogout).contents) if pUserLogout else CThostFtdcUserLogoutField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspUserLogout(self, pUserLogout:CThostFtdcUserLogoutField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 登出请求响应 """
        print('===OnRspUserLogout===:pUserLogout:CThostFtdcUserLogoutField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspQryMulticastInstrument(self, pMulticastInstrument:CThostFtdcMulticastInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspQryMulticastInstrument(copy.deepcopy(POINTER(CThostFtdcMulticastInstrumentField).from_param(pMulticastInstrument).contents) if pMulticastInstrument else CThostFtdcMulticastInstrumentField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspQryMulticastInstrument(self, pMulticastInstrument:CThostFtdcMulticastInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 请求查询组播合约响应 """
        print('===OnRspQryMulticastInstrument===:pMulticastInstrument:CThostFtdcMulticastInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspError(self, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspError(copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspError(self, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 错误应答 """
        print('===OnRspError===:pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspSubMarketData(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspSubMarketData(copy.deepcopy(POINTER(CThostFtdcSpecificInstrumentField).from_param(pSpecificInstrument).contents) if pSpecificInstrument else CThostFtdcSpecificInstrumentField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspSubMarketData(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 订阅行情应答 """
        print('===OnRspSubMarketData===:pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspUnSubMarketData(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspUnSubMarketData(copy.deepcopy(POINTER(CThostFtdcSpecificInstrumentField).from_param(pSpecificInstrument).contents) if pSpecificInstrument else CThostFtdcSpecificInstrumentField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspUnSubMarketData(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 取消订阅行情应答 """
        print('===OnRspUnSubMarketData===:pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspSubForQuoteRsp(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspSubForQuoteRsp(copy.deepcopy(POINTER(CThostFtdcSpecificInstrumentField).from_param(pSpecificInstrument).contents) if pSpecificInstrument else CThostFtdcSpecificInstrumentField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspSubForQuoteRsp(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 订阅询价应答 """
        print('===OnRspSubForQuoteRsp===:pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRspUnSubForQuoteRsp(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        self.OnRspUnSubForQuoteRsp(copy.deepcopy(POINTER(CThostFtdcSpecificInstrumentField).from_param(pSpecificInstrument).contents) if pSpecificInstrument else CThostFtdcSpecificInstrumentField(), copy.deepcopy(POINTER(CThostFtdcRspInfoField).from_param(pRspInfo).contents) if pRspInfo else CThostFtdcRspInfoField(), nRequestID, bIsLast)
    def OnRspUnSubForQuoteRsp(self, pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool):
        """ 取消订阅询价应答 """
        print('===OnRspUnSubForQuoteRsp===:pSpecificInstrument:CThostFtdcSpecificInstrumentField, pRspInfo:CThostFtdcRspInfoField, nRequestID:int, bIsLast:bool')
    
    def __OnRtnDepthMarketData(self, pDepthMarketData:CThostFtdcDepthMarketDataField):
        self.OnRtnDepthMarketData(copy.deepcopy(POINTER(CThostFtdcDepthMarketDataField).from_param(pDepthMarketData).contents) if pDepthMarketData else CThostFtdcDepthMarketDataField())
    def OnRtnDepthMarketData(self, pDepthMarketData:CThostFtdcDepthMarketDataField):
        """ 深度行情通知 """
        print('===OnRtnDepthMarketData===:pDepthMarketData:CThostFtdcDepthMarketDataField')
    
    def __OnRtnForQuoteRsp(self, pForQuoteRsp:CThostFtdcForQuoteRspField):
        self.OnRtnForQuoteRsp(copy.deepcopy(POINTER(CThostFtdcForQuoteRspField).from_param(pForQuoteRsp).contents) if pForQuoteRsp else CThostFtdcForQuoteRspField())
    def OnRtnForQuoteRsp(self, pForQuoteRsp:CThostFtdcForQuoteRspField):
        """ 询价通知 """
        print('===OnRtnForQuoteRsp===:pForQuoteRsp:CThostFtdcForQuoteRspField')
    