use super::visamini;
use std::thread::sleep;
use std::time::Duration;
#[derive(Default)]
pub struct Mt8000a {
    handle: Option<visamini::Visa1>,
}

impl Mt8000a {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }
    pub fn getdescrib(&mut self) -> Option<String> {
        if let Some(dd) = &mut self.handle {
            return dd.query("*IDN?");
        }
        None
    }
    pub fn open(&mut self, path: &str) -> bool {
        if let Some(rhand) = visamini::Visa1::new(path) {
            self.handle = Some(rhand);
            return true;
        }
        false
    }

    pub fn init(&mut self) -> bool {
        if let Some(dd) = &mut self.handle {
            return dd.send("*RST; *OPC?");
        }
        false
    }
    pub fn set_max_test_mt8000a(&mut self, nsa: bool) {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send("SIMMODELNUM P0250");
            sleep(Duration::from_millis(200));
            dd.send("INTEGRITY SNOW3G_128");
            sleep(Duration::from_millis(200));
            if nsa {
                dd.send("CIPHERING SNOW3G_128");
                sleep(Duration::from_millis(200));
            }
            dd.send("ULWAVEFORM DFTOFDM");
            sleep(Duration::from_millis(200));
            dd.send("ULMCS_TABLE 256QAM");
            sleep(Duration::from_millis(200));
            // dd.send("MAXULPWR 26");
            // sleep(Duration::from_millis(200));
            dd.query_while_key_time("MAXULPWR 26;MAXULPWR?", "26", 10); //pc2 功率等级
            dd.send("ULRMC_MOD QPSK");
            sleep(Duration::from_millis(200));
            dd.send("ILVL 25"); //IN level
            sleep(Duration::from_millis(200));
            dd.send("OLVL -30");
            sleep(Duration::from_millis(200));
            dd.send("TPCPAT All3"); //加3db
            sleep(Duration::from_millis(200));
        }
    }
    pub fn set_lte_loss<T: std::fmt::Display>(&mut self, lteul: T, ltedl: T) {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8821C");
            sleep(Duration::from_millis(500));
            dd.send("EXTLOSSW ON");
            sleep(Duration::from_millis(200));
            dd.send(&format!("ULEXTLOSS {}", lteul));
            sleep(Duration::from_millis(200));
            dd.send(&format!("DLEXTLOSS {}", ltedl));
            sleep(Duration::from_millis(200));
        };
    }
    pub fn set_nr_loss<T: std::fmt::Display>(&mut self, ul: T, dl: T) {
        //band data
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send("EXTLOSSW_IND SLOT1,ON");
            sleep(Duration::from_millis(200));
            dd.send(&format!("ULEXTLOSS_IND SLOT1,TRX1,{}", ul));
            sleep(Duration::from_millis(200));
            dd.send(&format!("DLEXTLOSS_IND SLOT1,TRX1,{}", dl));
            sleep(Duration::from_millis(200));
        }
    }
    fn isfdd(band: u64) -> bool {
        match band {
            1 | 2 | 3 | 5 | 7 | 8 | 12 | 13 | 14 | 18 | 20 | 25 | 26 | 28 | 30 | 66 | 71 => true,
            _ => false,
        }
    }
    pub fn set_mt8000a_nr_band(&mut self, band: u64) {
        if let Some(dd) = &mut self.handle {
            if Mt8000a::isfdd(band) {
                dd.send("FRAMETYPE FDD");
            } else {
                dd.send("FRAMETYPE TDD");
            }
            sleep(Duration::from_millis(200));
            dd.send(&format!("BAND {}", band));
            sleep(Duration::from_millis(200));
        }
    }
    pub fn mt8000a_nr_pcl_set(&mut self, band: u64) -> u64 {
        if let Some(dd) = &mut self.handle {
            match band {
                41 | 77 | 78 | 79 => {
                    dd.send("MAXULPWR 26"); //pc2 功率等级
                    sleep(Duration::from_millis(200));
                    return 26;
                }
                _ => {
                    dd.send("MAXULPWR 23"); //pc3 功率等级
                    sleep(Duration::from_millis(200));
                    return 23;
                }
            }
        }
        0
    }
    pub fn set_nr_tpc_max(&mut self, pcl: u64) {
        //ALL+3dbm
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send(&format!("ILVL {}", pcl));
            sleep(Duration::from_millis(200));
            dd.send("OLVL -30");
            sleep(Duration::from_millis(200));
            dd.send("TPCPAT ALL3");
            sleep(Duration::from_millis(200));
            dd.query_while_key_time("TPCPAT?", "ALL3", 10);
            sleep(Duration::from_millis(200));
        }
    }
    pub fn set_nr_tpc_10(&mut self) {
        //10dBm + Auto
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send("ILVL 10");
            sleep(Duration::from_millis(200));
            dd.send("OLVL -30");
            sleep(Duration::from_millis(200));
            dd.send("TPCPAT AUTO");
            sleep(Duration::from_millis(200));
            dd.query_while_key_time("TPCPAT?", "AUTO", 10);
        }
    }
    pub fn set_nr_tpc_0(&mut self) {
        //0dBm + Auto
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send("ILVL 0");
            sleep(Duration::from_millis(200));
            dd.send("OLVL -30");
            sleep(Duration::from_millis(200));
            dd.send("TPCPAT AUTO");
            sleep(Duration::from_millis(200));
            dd.query_while_key_time("TPCPAT?", "AUTO", 10);
        }
    }
    pub fn set_nr_tpc_min(&mut self) {
        //-35dbm + Auto
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.send("ILVL -35");
            sleep(Duration::from_millis(200));
            dd.send("OLVL -30");
            sleep(Duration::from_millis(200));
            dd.send("TPCPAT ALLM1");
            sleep(Duration::from_millis(200));
            dd.query_while_key_time("TPCPAT?", "ALLM1", 10);
        }
    }
    pub fn set_mt8000a_nr_width<T: std::fmt::Display>(&mut self, width: T) {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            dd.query_while_key_time(&format!("DLBANDWIDTH {}MHZ", width), &width.to_string(), 10);
        }
    }
    pub fn set_mt8000a_ulrmc_rb<T: std::fmt::Display>(&mut self, n_rb: T, s_rb: T) {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            sleep(Duration::from_millis(200));
            let mut ok_key = true;
            loop {
                ok_key = true;
                dd.send("ULWAVEFORM DFT-S-OFDM");
                sleep(Duration::from_millis(200));
                dd.send(&format!("ULRMC_RB {}", n_rb));
                sleep(Duration::from_millis(200));
                dd.send(&format!("ULRB_START {}", s_rb));
                sleep(Duration::from_millis(200));
                if let Err(_) = dd.query_and_confirm("ULRMC_RB?", &n_rb.to_string()) {
                    ok_key = false;
                };
                if let Err(_) = dd.query_and_confirm("ULRB_START?", &s_rb.to_string()) {
                    ok_key = false;
                };
                if ok_key {
                    break;
                }
                sleep(Duration::from_millis(5000));
            }
        }
    }
    pub fn set_mt8000a_inner_full(&mut self, band: u64, bandwidth: u64) {
        if Mt8000a::isfdd(band) {
            match bandwidth {
                50 => self.set_mt8000a_ulrmc_rb(135, 67),
                40 => self.set_mt8000a_ulrmc_rb(108, 54),
                30 => self.set_mt8000a_ulrmc_rb(80, 40),
                25 => self.set_mt8000a_ulrmc_rb(64, 32),
                20 => self.set_mt8000a_ulrmc_rb(50, 25),
                15 => self.set_mt8000a_ulrmc_rb(36, 18),
                10 => self.set_mt8000a_ulrmc_rb(25, 12),
                5 => self.set_mt8000a_ulrmc_rb(12, 6),
                _ => {}
            }
        } else {
            match bandwidth {
                100 => self.set_mt8000a_ulrmc_rb(135, 67),
                90 => self.set_mt8000a_ulrmc_rb(120, 60),
                80 => self.set_mt8000a_ulrmc_rb(108, 54),
                70 => self.set_mt8000a_ulrmc_rb(90, 45),
                60 => self.set_mt8000a_ulrmc_rb(81, 40),
                50 => self.set_mt8000a_ulrmc_rb(64, 32),
                40 => self.set_mt8000a_ulrmc_rb(50, 25),
                30 => self.set_mt8000a_ulrmc_rb(36, 18),
                25 => self.set_mt8000a_ulrmc_rb(32, 16),
                20 => self.set_mt8000a_ulrmc_rb(25, 12),
                15 => self.set_mt8000a_ulrmc_rb(18, 9),
                10 => self.set_mt8000a_ulrmc_rb(12, 6),
                5 => self.set_mt8000a_ulrmc_rb(5, 2),
                _ => {}
            }
        }
    }
    // pub fn set_lte_loss(&mut self,)
    pub fn set_mt8000a_to_ch<T: std::fmt::Display>(&mut self, channel: T) -> bool {
        if let Some(dd) = &mut self.handle {
            loop {
                dd.send(&format!("ULCHAN {}", channel));
                sleep(Duration::from_millis(200));
                if let Ok(_) =
                    dd.query_and_confirm(&format!("ULCHAN {}", channel), &channel.to_string())
                {
                    return true;
                };
            }
        }
        false
    }
    pub fn start_call_mt8000a(&mut self, times: u64) -> bool {
        if let Some(dd) = &mut self.handle {
            for idx in 0..times {
                if let Some(data) = dd.query("CALLSTAT?") {
                    sleep(Duration::from_millis(200));
                    if let Ok(s) = data.parse::<u64>() {
                        match s {
                            6 | 8 => {
                                //处于连接状态wcdma:7  lte:6
                                dd.send("CONTS");
                                return true;
                            }
                            1 | 2 => {
                                //呼叫
                                for idy in 0..5 {
                                    dd.send("CALLSA"); //开始呼叫
                                    sleep(Duration::from_secs(10));
                                    if let Some(data) = dd.query("CALLSTAT?") {
                                        sleep(Duration::from_secs(2));
                                        if let Ok(ss) = data.parse::<u64>() {
                                            match ss {
                                                6 | 8 => {
                                                    dd.send("CONTS");
                                                    return true;
                                                }
                                                _ => {}
                                            }
                                            sleep(Duration::from_secs(1));
                                        }
                                    }
                                }
                            }
                            _ => {
                                sleep(Duration::from_secs(1));
                            }
                        }
                    }
                };
            }
        }
        false
    }
    pub fn rem_dest_mt8000a(&mut self) {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
        }
    }
    pub fn end_mt8000a_status(&mut self) {
        if let Some(dd) = &mut self.handle {
            for _ in 0..3 {
                dd.send("CALLSO");
                sleep(Duration::from_secs(3));
            }
        }
    }
    pub fn read_mt8000a_power(&mut self) -> Option<String> {
        if let Some(dd) = &mut self.handle {
            dd.send("REM_DEST 8000A");
            dd.send("PWR_MEAS ON");
            sleep(Duration::from_millis(200));
            dd.send("PWR_AVG 20");
            sleep(Duration::from_millis(5000));

            return dd.query("POWER? AVG");
        }
        None
    }
}
