#![allow(unused_variables)]
use std::{env::var, path::Path, sync::Arc};

use ctp_dyn::{
    copy_str_to_i8_array, gb18030_cstr_i8_to_str, print_rsp_info,
    v1alpha1::{
        CThostFtdcDepthMarketDataField, CThostFtdcReqUserLoginField, CThostFtdcRspInfoField,
        CThostFtdcRspUserLoginField, CThostFtdcSpecificInstrumentField, MdApi, MdSpi,
    },
};

pub struct BaseMdSpi {
    pub(crate) mdapi: Arc<MdApi>,
}

impl MdSpi for BaseMdSpi {
    fn on_front_connected(&mut self) {
        let mut req = CThostFtdcReqUserLoginField::default();
        println!("mdspi.on_front_connected !!!");
        let user_id = var("SIMNOW_USER0").unwrap();
        copy_str_to_i8_array(&mut req.UserID, user_id.as_str());
        self.mdapi.req_user_login(&mut req, 1);
    }

    fn on_rsp_user_login(
        &mut self,
        rsp_user_login: Option<&CThostFtdcRspUserLoginField>,
        rsp_info: Option<&CThostFtdcRspInfoField>,
        request_id: i32,
        is_last: bool,
    ) {
        print_rsp_info!(rsp_info);
        println!("on_rsp_user_login!");

        if is_last {
            let instrument_ids = vec!["ag2502".to_string(), "fu2505".to_string()];
            self.mdapi.subscribe_market_data(&instrument_ids);
        }
    }

    fn on_rsp_sub_market_data(
        &mut self,
        specific_instrument: Option<&CThostFtdcSpecificInstrumentField>,
        rsp_info: Option<&CThostFtdcRspInfoField>,
        request_id: i32,
        is_last: bool,
    ) {
        print_rsp_info!(rsp_info);
        println!(
            "on_rsp_sub_market_data: instrument_id[{:?}], {:?}, {:?}",
            gb18030_cstr_i8_to_str(&specific_instrument.unwrap().InstrumentID),
            request_id,
            is_last
        );
    }

    fn on_rtn_depth_market_data(
        &mut self,
        depth_market_data: Option<&CThostFtdcDepthMarketDataField>,
    ) {
        println!("OnRtnDepthMarketData!");

        if let Some(q) = depth_market_data {
            println!(
                "tick: {} last_price: {}",
                gb18030_cstr_i8_to_str(&q.InstrumentID).unwrap(),
                q.LastPrice,
            )
        } else {
            panic!("tick null!");
        };
    }
}

fn main() {
    println!("mdapi start here!");

    let base_dir = var("CARGO_MANIFEST_DIR").unwrap();
    println!("base_dir: {base_dir}");
    #[cfg(target_os = "macos")]
    let dynlib_path =
        "./api/v6.7.2/v6.7.2_MacOS_20231016/thostmduserapi_se.framework/thostmduserapi_se";

    #[cfg(target_os = "linux")]
    let dynlib_path = "./api/v6.7.2/v6.7.2_20230913_api_traderapi_se_linux64/thostmduserapi_se.so";

    let dynlib_path = Path::new(&base_dir).join(dynlib_path);

    let mdapi = MdApi::create_api(dynlib_path, "./md_", false, false);

    let mdapi = Arc::new(mdapi);

    let base_mdspi: BaseMdSpi = BaseMdSpi {
        mdapi: Arc::clone(&mdapi),
    };
    let mdspi_box = Box::new(base_mdspi);
    println!("get_api_version: {}", mdapi.get_api_version());

    mdapi.register_front("tcp://180.168.146.187:10131");

    let mdspi_ptr = Box::into_raw(mdspi_box) as *mut dyn MdSpi;
    let mdspi_ptr2 = mdspi_ptr.clone();

    mdapi.register_spi(mdspi_ptr);

    mdapi.init();

    println!("mdapi init");

    mdapi.join();
    let _ = unsafe { Box::from_raw(mdspi_ptr2) };
}