/* generated by handle_module_api */
use std::{
    cell::Cell,
    ffi::{CStr, CString},
    os::raw::c_char,
    path::Path,
    ptr::null_mut,
};

use libloading::Library;

use crate::v1alpha1::bindings::*;
use crate::v1alpha1::mdspi::*;    

pub struct MdApi {
    pub api_ptr: *mut CThostFtdcMdApi,
    pub spi_ptr: Cell<* mut CThostFtdcMdSpiExt>,
    pub dynlib: Option<Library>,          
}

unsafe impl Sync for MdApi {}
unsafe impl Send for MdApi {}

impl MdApi {
        /// 删除接口对象本身
    ///@remark 不再使用本接口对象时,调用该函数删除接口对象
    pub fn release(&self) {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_Release)(self.api_ptr)
        }
    }
    
    /// 初始化
    ///@remark 初始化运行环境,只有调用后,接口才开始工作
    pub fn init(&self) {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_Init)(self.api_ptr)
        }
    }
    
    /// 等待接口线程结束运行
    ///@return 线程退出代码
    pub fn join(&self) -> i32 {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_Join)(self.api_ptr)
        }
    }
    
    /// 获取当前交易日
    ///@retrun 获取到的交易日
    ///@remark 只有登录成功后,才能得到正确的交易日
    pub fn get_trading_day(&self) -> String {
        unsafe {
            let cstr_ptr = ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_GetTradingDay)(self.api_ptr);
            let c_str = CStr::from_ptr(cstr_ptr);
            c_str.to_string_lossy().to_string()
        }
    }
    
    /// 注册前置机网络地址
    ///@param pszFrontAddress:前置机网络地址。
    ///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:17001”。
    ///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”17001”代表服务器端口号。
    pub fn register_front(&self, psz_front_address: &str) {
        unsafe {
            let psz_front_address = CString::new(psz_front_address).unwrap();
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_RegisterFront)(self.api_ptr, psz_front_address.as_ptr() as *mut i8)
        }
    }
    
    /// 注册名字服务器网络地址
    ///@param pszNsAddress:名字服务器网络地址。
    ///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:12001”。
    ///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”12001”代表服务器端口号。
    ///@remark RegisterNameServer优先于RegisterFront
    pub fn register_name_server(&self, psz_ns_address: &str) {
        unsafe {
            let psz_ns_address = CString::new(psz_ns_address).unwrap();
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_RegisterNameServer)(self.api_ptr, psz_ns_address.as_ptr() as *mut i8)
        }
    }
    
    /// 注册名字服务器用户信息
    ///@param pFensUserInfo:用户信息。
    pub fn register_fens_user_info(&self, p_fens_user_info: &mut CThostFtdcFensUserInfoField) {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_RegisterFensUserInfo)(self.api_ptr, p_fens_user_info as *mut CThostFtdcFensUserInfoField)
        }
    }
    
    /// 注册回调接口
    ///@param pSpi 派生自回调接口类的实例
    pub fn register_spi(&self, p_spi: *mut dyn MdSpi) {
        let spi_ptr = Box::into_raw(Box::new(CThostFtdcMdSpiExt::new(p_spi)));
        let last_spi_ptr = self.spi_ptr.get();
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_RegisterSpi)(self.api_ptr, spi_ptr as _)
        }
        self.spi_ptr.set(spi_ptr);
        if !last_spi_ptr.is_null() {
            unsafe {
                let _ = Box::from_raw(last_spi_ptr); // 释放动态分配的内存
            }
        }
    }
    
    /// 订阅行情。
    ///@param ppInstrumentID 合约ID
    ///@param nCount 要订阅/退订行情的合约个数
    ///@remark
    pub fn subscribe_market_data(&self, pp_instrument_id: &Vec<String>) -> i32 {
        let cstrings: Vec<_> = pp_instrument_id.iter().map(|x| CString::new(x.clone()).unwrap()).collect();
        let cstr_slice: Vec<*const i8> = cstrings.iter().map(|cstr| cstr.as_ptr()).collect();
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_SubscribeMarketData)(self.api_ptr, cstr_slice.as_ptr() as *mut *mut i8, pp_instrument_id.len() as i32)
        }    
    }
    
    /// 退订行情。
    ///@param ppInstrumentID 合约ID
    ///@param nCount 要订阅/退订行情的合约个数
    ///@remark
    pub fn unsubscribe_market_data(&self, pp_instrument_id: &Vec<String>) -> i32 {
        let cstrings: Vec<_> = pp_instrument_id.iter().map(|x| CString::new(x.clone()).unwrap()).collect();
        let cstr_slice: Vec<*const i8> = cstrings.iter().map(|cstr| cstr.as_ptr()).collect();
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_UnSubscribeMarketData)(self.api_ptr, cstr_slice.as_ptr() as *mut *mut i8, pp_instrument_id.len() as i32)
        }    
    }
    
    /// 订阅询价。
    ///@param ppInstrumentID 合约ID
    ///@param nCount 要订阅/退订行情的合约个数
    ///@remark
    pub fn subscribe_for_quote_rsp(&self, pp_instrument_id: &Vec<String>) -> i32 {
        let cstrings: Vec<_> = pp_instrument_id.iter().map(|x| CString::new(x.clone()).unwrap()).collect();
        let cstr_slice: Vec<*const i8> = cstrings.iter().map(|cstr| cstr.as_ptr()).collect();
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_SubscribeForQuoteRsp)(self.api_ptr, cstr_slice.as_ptr() as *mut *mut i8, pp_instrument_id.len() as i32)
        }    
    }
    
    /// 退订询价。
    ///@param ppInstrumentID 合约ID
    ///@param nCount 要订阅/退订行情的合约个数
    ///@remark
    pub fn unsubscribe_for_quote_rsp(&self, pp_instrument_id: &Vec<String>) -> i32 {
        let cstrings: Vec<_> = pp_instrument_id.iter().map(|x| CString::new(x.clone()).unwrap()).collect();
        let cstr_slice: Vec<*const i8> = cstrings.iter().map(|cstr| cstr.as_ptr()).collect();
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_UnSubscribeForQuoteRsp)(self.api_ptr, cstr_slice.as_ptr() as *mut *mut i8, pp_instrument_id.len() as i32)
        }    
    }
    
    /// 用户登录请求
    pub fn req_user_login(&self, p_req_user_login_field: &mut CThostFtdcReqUserLoginField, n_request_id: i32) -> i32 {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_ReqUserLogin)(self.api_ptr, p_req_user_login_field as *mut CThostFtdcReqUserLoginField, n_request_id)
        }
    }
    
    /// 登出请求
    pub fn req_user_logout(&self, p_user_logout: &mut CThostFtdcUserLogoutField, n_request_id: i32) -> i32 {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_ReqUserLogout)(self.api_ptr, p_user_logout as *mut CThostFtdcUserLogoutField, n_request_id)
        }
    }
    
    /// 请求查询组播合约
    pub fn req_qry_multicast_instrument(&self, p_qry_multicast_instrument: &mut CThostFtdcQryMulticastInstrumentField, n_request_id: i32) -> i32 {
        unsafe {
            ((*(*self.api_ptr).vtable_).CThostFtdcMdApi_ReqQryMulticastInstrument)(self.api_ptr, p_qry_multicast_instrument as *mut CThostFtdcQryMulticastInstrumentField, n_request_id)
        }
    }
    
}