use core::sync::atomic::{AtomicBool, Ordering};

use alloc::{
    sync::{Arc, Weak},
    vec::Vec,
};
use bitmap::{traits::BitMapOps, StaticBitmap};
use log::warn;

use crate::{
    driver::{
        serial::serial8250::send_to_default_serial8250_port,
        tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
    },
    libs::{font::FontDesc, rwlock::RwLock},
    process::Pid,
};

use super::{
    console_map::{TranslationMap, TranslationMapType},
    vc_manager, Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN,
    DEFAULT_RED,
};

pub(super) const NPAR: usize = 16;

lazy_static! {
    /// 是否已经添加了软光标
    pub(super) static ref SOFTCURSOR_ORIGINAL: RwLock<Option<VcCursor>> = RwLock::new(None);


}

pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);

/// ## 虚拟控制台的信息
#[derive(Debug, Clone)]
pub struct VirtualConsoleData {
    pub vc_index: usize,
    pub state: VirtualConsoleInfo,
    pub saved_state: VirtualConsoleInfo,
    /// 最大列数
    pub cols: usize,
    /// 最大行数
    pub rows: usize,
    // ///  每行的字节数
    // pub bytes_per_row: usize,
    /// 扫描行数
    pub scan_lines: usize,
    /// 字符单元高度
    pub cell_height: u32,

    // /// 实际屏幕地址的开始
    // pub screen_base: VirtAddr,
    // /// 实际屏幕的结束
    // pub scr_end: u64,
    /// 可见窗口的开始
    pub visible_origin: usize,
    /// 滚动窗口的顶部
    pub top: usize,
    /// 滚动窗口的底部
    pub bottom: usize,
    /// 当前读取位置
    pub pos: usize,

    /// 颜色集合
    pub palette: [Color; 16],
    /// 默认颜色
    pub def_color: u8,
    /// 下划线颜色
    pub underline_color: u32,
    /// 斜体颜色
    pub italic_color: u32,
    /// 半强度颜色
    pub half_color: u32,

    pub mode: KDMode,
    pub vt_mode: VtModeData,

    /// 是否启用颜色
    pub color_mode: bool,

    // 字符
    pub hi_font_mask: u16,
    pub font: ConsoleFont,

    pub erase_char: u16,

    pub complement_mask: u16,
    pub s_complement_mask: u16,

    pub cursor_blink_ms: u16,

    pub pid: Option<Pid>,
    pub index: usize,

    pub vc_state: VirtualConsoleState,

    // 一些标志
    /// 指示是否显示 ASCII 字符小于 32 的控制字符(vc_disp_ctrl)
    pub display_ctrl: bool,
    /// 指示是否切换高位（meta）位。Meta 键是一个特殊的按键，用于扩展字符集。
    pub toggle_meta: bool,
    /// 表示屏幕模式(vc_decscnm)
    pub screen_mode: bool,
    /// 指定光标移动的起始位置，是相对于屏幕的左上角还是相对于当前页的左上角(vc_decom)
    pub origin_mode: bool,
    /// 控制光标到达行末时是否自动换行(vc_decawm)
    pub autowrap: bool,
    /// 控制光标的可见性(vc_deccm)
    pub cursor_visible: bool,
    /// 光标相关
    pub cursor_type: VcCursor,
    /// 控制插入或替换模式(vc_decim)
    pub insert_mode: bool,
    /// 表示一些私有模式或状态，通常由特定终端实现定义(vc_priv)
    pub private: Vt102_OP,
    /// 是否需要进行自动换行
    pub need_wrap: bool,
    /// 控制鼠标事件的报告方式
    pub report_mouse: u8,
    /// 指示终端是否使用 UTF-8 编码
    pub utf: bool,
    /// UTF-8 编码的字符计数，表示还需要多少个字节才能够构建完成
    pub utf_count: u8,
    /// UTF-8 编码的字符，表示正在构建的utf字符
    pub utf_char: u32,
    /// 构建utf时需要的参数，表示目前接收了多少个字节的数据来构建utf字符
    pub npar: u32,
    pub par: [u32; NPAR],

    /// 字符转换表 用于将输入字符映射到特定的字符
    pub translate: TranslationMap,

    pub tab_stop: StaticBitmap<256>,

    pub attr: u8,

    /// vc缓冲区
    pub screen_buf: Vec<u16>,

    /// 对应的Console Driver funcs
    driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
}

impl VirtualConsoleData {
    #[inline(never)]
    pub fn new(num: usize) -> Self {
        Self {
            state: VirtualConsoleInfo::new(0, 0),
            saved_state: Default::default(),
            cols: Default::default(),
            rows: Default::default(),
            // bytes_per_row: Default::default(),
            scan_lines: Default::default(),
            cell_height: Default::default(),
            // origin: Default::default(),
            // scr_end: Default::default(),
            visible_origin: Default::default(),
            top: Default::default(),
            bottom: Default::default(),
            palette: [Default::default(); 16],
            def_color: Default::default(),
            underline_color: Default::default(),
            italic_color: Default::default(),
            half_color: Default::default(),
            mode: Default::default(),
            color_mode: Default::default(),
            hi_font_mask: Default::default(),
            erase_char: Default::default(),
            complement_mask: Default::default(),
            s_complement_mask: Default::default(),
            cursor_blink_ms: 200,
            pos: Default::default(),
            vt_mode: VtModeData {
                mode: VtMode::Auto,
                relsig: 0,
                acqsig: 0,
            },
            pid: None,
            index: 0,
            font: Default::default(),
            vc_state: VirtualConsoleState::ESnormal,
            display_ctrl: Default::default(),
            toggle_meta: Default::default(),
            screen_mode: Default::default(),
            origin_mode: Default::default(),
            autowrap: Default::default(),
            cursor_visible: Default::default(),
            insert_mode: Default::default(),
            private: Vt102_OP::Pecma,
            need_wrap: Default::default(),
            report_mouse: Default::default(),
            utf: Default::default(),
            utf_count: Default::default(),
            utf_char: Default::default(),
            translate: TranslationMap::new(TranslationMapType::Lat1),
            npar: Default::default(),
            tab_stop: StaticBitmap::new(),
            par: [0; 16],
            attr: Default::default(),
            screen_buf: Default::default(),
            driver_funcs: None,
            cursor_type: VcCursor::empty(),
            vc_index: num,
        }
    }

    pub fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
        if let Some(rows) = rows {
            self.rows = rows;
        }
        if let Some(cols) = cols {
            self.cols = cols;
        }

        self.pos = self.cols * self.state.y + self.state.x;
        // self.bytes_per_row = self.cols << 1;

        self.def_color = 15; // white
        self.italic_color = 2; // green
        self.underline_color = 3; // cyan
        self.half_color = 0x08; // grey

        self.screen_buf.resize(self.cols * self.rows, 0);
        self.reset(clear);
    }

    pub fn should_update(&self) -> bool {
        self.is_visible() && !CONSOLE_BLANKED.load(Ordering::SeqCst)
    }

    pub fn is_visible(&self) -> bool {
        if let Some(cur_vc) = vc_manager().current_vc_index() {
            cur_vc == self.vc_index
        } else {
            false
        }
    }

    fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {
        self.driver_funcs.as_ref().unwrap().upgrade().unwrap()
    }

    pub fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) {
        self.driver_funcs = Some(func);
    }

    pub(super) fn reset(&mut self, do_clear: bool) {
        self.mode = KDMode::KdText;
        // unicode?
        self.vt_mode.mode = VtMode::Auto;
        self.vt_mode.acqsig = 0;
        self.vt_mode.relsig = 0;
        self.display_ctrl = false;
        self.toggle_meta = false;
        self.screen_mode = false;
        self.origin_mode = false;
        self.autowrap = true;
        self.cursor_visible = true;
        self.insert_mode = false;
        self.need_wrap = false;
        self.report_mouse = 0;
        self.utf_count = 0;
        self.translate = TranslationMap::new(TranslationMapType::Lat1);
        self.utf = true;
        self.pid = None;
        self.vc_state = VirtualConsoleState::ESnormal;
        self.reset_palette();
        // self.cursor_type = VcCursor::CUR_UNDERLINE;
        self.cursor_type = VcCursor::CUR_BLOCK;

        self.default_attr();
        self.update_attr();

        self.tab_stop.set_all(false);

        for i in (0..256).step_by(8) {
            self.tab_stop.set(i, true);
        }

        self.state.x = 0;
        self.state.y = 0;
        self.pos = 0;

        if do_clear {
            self.csi_J(2);
        }
    }

    fn reset_palette(&mut self) {
        for (idx, color) in self.palette.iter_mut().enumerate() {
            color.red = DEFAULT_RED[idx];
            color.green = DEFAULT_GREEN[idx];
            color.blue = DEFAULT_BLUE[idx];
        }

        self.set_palette();
    }

    fn set_palette(&self) {
        if self.mode != KDMode::KdGraphics {
            // todo: 通知driver层的Console
            let _ = self.driver_funcs().con_set_palette(self, COLOR_TABLE);
        }
    }

    /// ## 翻译字符，将字符转换为终端控制符
    /// ### 参数
    ///
    /// ### c: 需要转换的字符
    ///
    /// ### 返回值
    /// ### （转换后的字符:i32，是否需要更多的数据才能进行转换:bool）
    pub fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) {
        if self.vc_state != VirtualConsoleState::ESnormal {
            // 在控制字符状态下不需要翻译
            return (Some(*c), false);
        }
        if self.utf && !self.display_ctrl {
            // utf模式并且不显示控制字符
            let (ret, rescan) = self.translate_unicode(*c);
            if let Some(ret) = ret {
                *c = ret;
            }
            return (ret, rescan);
        }

        return (Some(self.translate_ascii(*c)), false);
    }

    /// 该数组包含每个字节序列长度变化的阈值
    /// 即如果由两个字节组成的unicode字符，则长度应该在UTF8_LENGTH_CHANGES[0] ~ UTF8_LENGTH_CHANGES[1]之间
    const UTF8_LENGTH_CHANGES: &'static [u32] = &[
        0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff,
    ];

    /// ## 翻译字符，将UTF-8 编码的字符转换为 Unicode 编码
    /// ### 参数
    ///
    /// ### c: 需要转换的字符
    ///
    /// ### 返回值
    /// ### （转换后的字符:i32，是否需要重新传入该字符:bool）
    ///
    /// !!! 注意，该函数返回true时，元组的第一个数据是无效数据（未转换完成）
    fn translate_unicode(&mut self, c: u32) -> (Option<u32>, bool) {
        // 收到的字符不是首个
        if (c & 0xc0) == 0x80 {
            // 已经不需要继续的字符了，说明这个字符是非法的
            if self.utf_count == 0 {
                return (Some(0xfffd), false);
            }

            self.utf_char = (self.utf_char << 6) | (c & 0x3f);
            self.npar += 1;

            self.utf_count -= 1;
            if self.utf_count > 0 {
                // 表示需要更多字节
                return (None, false);
            }

            let c = self.utf_char;

            // 先检查一遍是否合格
            if c <= Self::UTF8_LENGTH_CHANGES[self.npar as usize - 1]
                || c > Self::UTF8_LENGTH_CHANGES[self.npar as usize]
            {
                return (Some(0xfffd), false);
            }

            return (Some(Self::sanitize_unicode(c)), false);
        }

        // 接收到单个ASCII字符或者一个序列的首字符,且上次的未处理完,则上一个字符视为无效，则需要重新传入该字符处理
        if self.utf_count > 0 {
            self.utf_count = 0;
            return (Some(0xfffd), true);
        }

        // ascii
        if c <= 0x7f {
            return (Some(c), false);
        }

        // 第一个字节
        self.npar = 0;
        if (c & 0xe0) == 0xc0 {
            self.utf_count = 1;
            self.utf_char = c & 0x1f;
        } else if (c & 0xf0) == 0xe0 {
            self.utf_count = 2;
            self.utf_char = c & 0x0f;
        } else if (c & 0xf8) == 0xf0 {
            self.utf_count = 3;
            self.utf_char = c & 0x07;
        } else if (c & 0xfc) == 0xf8 {
            self.utf_count = 4;
            self.utf_char = c & 0x03;
        } else if (c & 0xfe) == 0xfc {
            self.utf_count = 5;
            self.utf_char = c & 0x01;
        } else {
            /* 254 and 255 are invalid */
            return (Some(0xfffd), false);
        }

        (None, false)
    }

    /// ## 翻译字符，将字符转换为Ascii
    fn translate_ascii(&self, c: u32) -> u32 {
        let mut c = c;
        if self.toggle_meta {
            c |= 0x80;
        }

        return self.translate.translate(c) as u32;
    }

    /// ## 用于替换无效的 Unicode 代码点（code points）。
    /// Unicode 代码点的范围是从 U+0000 到 U+10FFFF，
    /// 但是有一些特殊的代码点是无效的或者保留给特定用途的。
    /// 这个函数的主要目的是将无效的 Unicode 代码点替换为 U+FFFD，即 Unicode 替代字符。
    fn sanitize_unicode(c: u32) -> u32 {
        if (0xd800..=0xdfff).contains(&c) || c == 0xfffe || c == 0xffff {
            return 0xfffd;
        }
        return c;
    }

    /// 用于表示小于 32 的字符中，哪些字符对应的位被设置为 1，
    /// 表示这些字符会触发一些特殊的动作，比如光标移动等。
    /// 这些字符在 disp_ctrl 模式未开启时不应该被显示为图形符号
    const CTRL_ACTION: u32 = 0x0d00ff81;
    /// 用于表示哪些控制字符是始终显示的，即便 disp_ctrl 模式未开启。
    /// 这些字符对于终端来说是必要的，显示它们是为了保证终端正常工作。
    /// 这些字符在 disp_ctrl 模式开启或关闭时都应该显示为控制字符。
    const CTRL_ALWAYS: u32 = 0x0800f501;

    /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符
    pub fn is_control(&self, tc: u32, c: u32) -> bool {
        // 当前vc状态机不在正常状态，即在接收特殊字符的状态，则是控制字符
        if self.vc_state != VirtualConsoleState::ESnormal {
            return true;
        }

        if tc == 0 {
            return true;
        }

        if c < 32 {
            if self.display_ctrl {
                // 查看在位图中是否有该字符
                return Self::CTRL_ALWAYS & (1 << c) != 0;
            } else {
                return self.utf || (Self::CTRL_ACTION & (1 << c) != 0);
            }
        }

        if c == 127 && !self.display_ctrl {
            return true;
        }

        if c == 128 + 27 {
            return true;
        }

        false
    }

    pub(super) fn set_cursor(&mut self) {
        if self.mode == KDMode::KdGraphics {
            return;
        }

        if self.cursor_visible {
            // TODO: 处理选择
            self.add_softcursor();
            if self.cursor_type.cursor_size() != VcCursor::CUR_NONE {
                self.driver_funcs().con_cursor(self, CursorOperation::Draw);
            }
        } else {
            self.hide_cursor();
        }
    }

    /// ## 添加软光标
    fn add_softcursor(&mut self) {
        let mut i = self.screen_buf[self.pos] as u32;
        let cursor_type = self.cursor_type;

        if !cursor_type.contains(VcCursor::CUR_SW) {
            return;
        }

        if SOFTCURSOR_ORIGINAL.read_irqsave().is_some() {
            // 已经设置了软光标
            return;
        }

        let mut soft_cursor_guard = SOFTCURSOR_ORIGINAL.write_irqsave();
        *soft_cursor_guard = Some(unsafe { VcCursor::from_bits_unchecked(i) });

        let soft_cursor = soft_cursor_guard.unwrap();

        i |= cursor_type.cursor_set();
        i ^= cursor_type.cursor_change();
        if cursor_type.contains(VcCursor::CUR_ALWAYS_BG)
            && ((soft_cursor.bits & VcCursor::CUR_BG.bits) == (i & VcCursor::CUR_BG.bits))
        {
            i ^= VcCursor::CUR_BG.bits;
        }
        if cursor_type.contains(VcCursor::CUR_INVERT_FG_BG)
            && ((i & VcCursor::CUR_FG.bits) == ((i & VcCursor::CUR_BG.bits) >> 4))
        {
            i ^= VcCursor::CUR_FG.bits;
        }

        self.screen_buf[self.pos] = i as u16;

        let _ =
            self.driver_funcs()
                .con_putc(self, i as u16, self.state.y as u32, self.state.x as u32);
    }

    pub fn hide_cursor(&mut self) {
        // TODO: 处理选择

        self.driver_funcs().con_cursor(self, CursorOperation::Erase);
        self.hide_softcursor();
    }

    fn hide_softcursor(&mut self) {
        let softcursor = SOFTCURSOR_ORIGINAL.upgradeable_read_irqsave();
        if softcursor.is_some() {
            self.screen_buf[self.pos] = softcursor.unwrap().bits as u16;
            let _ = self.driver_funcs().con_putc(
                self,
                softcursor.unwrap().bits as u16,
                self.state.y as u32,
                self.state.x as u32,
            );

            *softcursor.upgrade() = None;
        }
    }

    fn gotoxay(&mut self, x: i32, y: i32) {
        if self.origin_mode {
            self.gotoxy(x, self.top as i32 + y);
        } else {
            self.gotoxy(x, y)
        }
    }

    // ## 将当前vc的光标移动到目标位置
    fn gotoxy(&mut self, x: i32, y: i32) {
        if x < 0 {
            self.state.x = 0;
        } else if x as usize >= self.cols {
            self.state.x = self.cols - 1;
        } else {
            self.state.x = x as usize;
        }

        let max_y;
        let min_y;
        if self.origin_mode {
            min_y = self.top;
            max_y = self.bottom - 1;
        } else {
            min_y = 0;
            max_y = self.rows - 1;
        }

        if y < min_y as i32 {
            self.state.y = min_y;
        } else if y >= max_y as i32 {
            self.state.y = max_y;
        } else {
            self.state.y = y as usize;
        }

        self.pos = self.state.y * self.cols + self.state.x;
        self.need_wrap = false;
    }

    fn scroll(&mut self, dir: ScrollDir, mut nr: usize) {
        // todo: uniscr_srceen
        if self.top + nr >= self.bottom {
            // 滚动超过一页,则按一页计算
            nr = self.bottom - self.top - 1;
        }

        if nr < 1 {
            return;
        }

        if self.is_visible()
            && self
                .driver_funcs()
                .con_scroll(self, self.top, self.bottom, dir, nr)
        {
            // 如果成功
            return;
        }

        // 调整screen_buf
        let count = nr * self.cols;
        if dir == ScrollDir::Up {
            for i in self.screen_buf[0..count].iter_mut() {
                *i = self.erase_char;
            }
            self.screen_buf.rotate_left(count);
        } else if dir == ScrollDir::Down {
            todo!();
        }
    }

    /// ## 退格
    fn backspace(&mut self) {
        if self.state.x > 0 {
            self.pos -= 1;
            self.state.x -= 1;
            self.need_wrap = false;

            // TODO: notify
        }
    }

    /// ## 换行
    fn line_feed(&mut self) {
        if self.state.y + 1 == self.bottom {
            self.scroll(ScrollDir::Up, 1);
        } else if self.state.y < self.rows - 1 {
            self.state.y += 1;
            self.pos += self.cols;
        }

        self.need_wrap = false;
        // TODO: Notify write
    }

    /// ## 回车
    fn carriage_return(&mut self) {
        // 写入位置回退到该行最前
        self.pos -= self.state.x;
        self.need_wrap = false;
        self.state.x = 0;
    }

    /// ## Del
    fn delete(&mut self) {
        // ignore
    }

    /// ## 向上滚动虚拟终端的内容，或者将光标上移一行
    fn reverse_index(&mut self) {
        if self.state.y == self.top {
            self.scroll(ScrollDir::Down, 1);
        } else if self.state.y > 0 {
            self.state.y -= 1;
            self.pos -= self.cols;
        }
        self.need_wrap = false;
    }

    /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#restore_cur
    fn restore_cursor(&mut self) {
        self.saved_state = self.state.clone();

        self.gotoxy(self.state.x as i32, self.state.y as i32);

        // TODO Gx_charset

        self.update_attr();
        self.need_wrap = false;
        todo!()
    }

    /// ## 设置当前vt的各项属性
    fn set_mode(&mut self, on_off: bool) {
        for i in 0..self.npar as usize {
            if self.private == Vt102_OP::Pdec {
                match self.par[i] {
                    1 => {
                        todo!("kbd todo");
                    }
                    3 => {
                        todo!("reisze todo");
                    }
                    5 => {
                        todo!("invert_screen todo");
                    }
                    6 => {
                        self.origin_mode = on_off;
                        if on_off {
                            self.gotoxy(0, self.top as i32);
                        } else {
                            self.gotoxy(0, 0);
                        }
                    }
                    7 => {
                        self.autowrap = on_off;
                    }
                    8 => {
                        todo!("kbd todo");
                    }
                    9 => {
                        todo!("report mouse todo");
                    }
                    25 => {
                        self.cursor_visible = on_off;
                    }
                    1000 => {
                        todo!("report mouse todo");
                    }
                    _ => {}
                }
            } else {
                match self.par[i] {
                    3 => {
                        self.display_ctrl = on_off;
                    }
                    4 => {
                        self.insert_mode = on_off;
                    }
                    20 => {
                        todo!("kbd todo");
                    }
                    _ => {}
                }
            }
        }
    }

    #[inline(never)]
    fn do_getpars(&mut self, c: char) {
        if c == ';' && self.npar < (NPAR - 1) as u32 {
            self.npar += 1;
            return;
        }

        if c.is_ascii_digit() {
            self.par[self.npar as usize] *= 10;
            self.par[self.npar as usize] += (c as u8 - b'0') as u32;
            return;
        }

        if c as u8 >= 0x20 && c as u8 <= 0x3f {
            self.vc_state = VirtualConsoleState::EScsiignore;
            return;
        }

        self.vc_state = VirtualConsoleState::ESnormal;

        match c {
            'h' => {
                if self.private <= Vt102_OP::Pdec {
                    self.set_mode(true);
                }
                return;
            }
            'l' => {
                if self.private <= Vt102_OP::Pdec {
                    self.set_mode(false);
                }
                return;
            }
            'c' => {
                if self.private == Vt102_OP::Pdec {
                    if self.par[0] != 0 {
                        self.cursor_type =
                            VcCursor::make_cursor(self.par[0], self.par[1], self.par[2])
                    } else {
                        self.cursor_type = VcCursor::CUR_UNDERLINE;
                    }
                    return;
                }
            }
            'm' => {
                if self.private == Vt102_OP::Pdec {
                    if self.par[0] != 0 {
                        self.complement_mask = (self.par[0] << 8 | self.par[1]) as u16;
                    } else {
                        self.complement_mask = self.s_complement_mask;
                    }
                    return;
                }
            }
            'n' => {
                if self.private == Vt102_OP::Pecma {
                    if self.par[0] == 5 {
                        send_to_default_serial8250_port("tty status report todo".as_bytes());
                        panic!();
                    } else if self.par[0] == 6 {
                        send_to_default_serial8250_port("tty cursor report todo".as_bytes());
                        panic!();
                    }
                }
                return;
            }
            _ => {}
        }

        if self.private != Vt102_OP::Pecma {
            self.private = Vt102_OP::Pecma;
            return;
        }

        match c {
            'G' | '`' => {
                if self.par[0] != 0 {
                    self.par[0] -= 1;
                }
                self.gotoxy(self.par[0] as i32, self.state.y as i32);
                return;
            }
            'A' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(
                    self.state.x as i32,
                    (self.state.y - self.par[0] as usize) as i32,
                );
                return;
            }
            'B' | 'e' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(
                    self.state.x as i32,
                    (self.state.y + self.par[0] as usize) as i32,
                );
                return;
            }
            'C' | 'a' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(
                    (self.state.x + self.par[0] as usize) as i32,
                    self.state.y as i32,
                );
                return;
            }
            'D' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(
                    self.state.x as i32 - self.par[0] as i32,
                    self.state.y as i32,
                );
                return;
            }
            'E' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(0, (self.state.y + self.par[0] as usize) as i32);
                return;
            }
            'F' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                self.gotoxy(0, self.state.y as i32 - self.par[0] as i32);
                return;
            }
            'd' => {
                if self.par[0] != 0 {
                    self.par[0] -= 1;
                }
                self.gotoxay(self.state.x as i32, self.par[0] as i32);
                return;
            }
            'H' | 'f' => {
                // MOVETO
                if self.par[0] != 0 {
                    self.par[0] -= 1;
                }
                if self.par[1] != 0 {
                    self.par[1] -= 1;
                }
                self.gotoxay(self.par[1] as i32, self.par[0] as i32);
                return;
            }
            'J' => {
                self.csi_J(self.par[0]);
                return;
            }
            'K' => {
                self.csi_K(self.par[0]);
                return;
            }
            'L' => {
                todo!("csi_L todo");
            }
            'M' => {
                todo!("csi_M todo");
            }
            'P' => {
                todo!("csi_P todo");
            }

            // 非ANSI标准，为ANSI拓展
            'S' => {
                self.scroll(ScrollDir::Up, self.par[0] as usize);
                return;
            }

            'T' => {
                self.scroll(ScrollDir::Down, self.par[0] as usize);
                return;
            }

            'c' => {
                if self.par[0] == 0 {
                    warn!("respone ID todo");
                }
                return;
            }
            'g' => {
                if self.par[0] == 0 && self.state.x < 256 {
                    self.tab_stop.set(self.state.x, true);
                } else if self.par[0] == 3 {
                    self.tab_stop.set_all(false);
                }
                return;
            }
            'm' => {
                self.csi_m();
                return;
            }
            'q' => {
                if self.par[0] < 4 {
                    todo!("vt set led state todo");
                }
                return;
            }
            'r' => {
                if self.par[0] == 0 {
                    self.par[0] += 1;
                }
                if self.par[1] == 0 {
                    self.par[1] = self.rows as u32;
                }
                if self.par[0] < self.par[1] && self.par[1] <= self.rows as u32 {
                    self.top = self.par[0] as usize - 1;
                    self.bottom = self.par[1] as usize;
                    self.gotoxay(0, 0);
                }
                return;
            }
            's' => {
                self.saved_state = self.state.clone();
                return;
            }
            'u' => {
                self.restore_cursor();
                return;
            }
            '@' => {
                todo!("csi_at todo");
            }
            ']' => {
                todo!("set termial command todo");
            }
            _ => {}
        }
    }

    /// ##  处理Control Sequence Introducer（控制序列引导符） m字符
    #[inline(never)]
    fn csi_m(&mut self) {
        let mut i = 0;
        loop {
            if i > self.npar as usize {
                break;
            }
            match self.par[i] {
                0 => {
                    // 关闭所有属性
                    self.default_attr();
                }

                1 => {
                    // 设置粗体
                    self.state.intensity = VirtualConsoleIntensity::Bold;
                }

                2 => {
                    // 设置半亮度（半明显
                    self.state.intensity = VirtualConsoleIntensity::HalfBright;
                }

                3 => {
                    // 斜体
                    self.state.italic = true;
                }

                4 | 21 => {
                    // 下划线

                    // 21是设置双下划线，但是不支持，就单下划线
                    self.state.underline = true;
                }

                5 => {
                    // 设置闪烁
                    self.state.blink = true;
                }

                7 => {
                    // 设置反显（前景色与背景色对调）
                    self.state.reverse = true;
                }

                10 => {
                    // 选择主要字体
                    todo!()
                }

                11 => {
                    // 选择第一个替代字体
                    todo!()
                }

                12 => {
                    // 选择第二个替代字体
                    todo!()
                }

                22 => {
                    //  关闭粗体和半亮度，恢复正常亮度
                    self.state.intensity = VirtualConsoleIntensity::Normal;
                }

                23 => {
                    // 关闭斜体
                    self.state.italic = false;
                }

                24 => {
                    // 关闭下划线
                    self.state.underline = false;
                }

                25 => {
                    // 关闭字符闪烁
                    self.state.blink = false;
                }

                27 => {
                    // 关闭反显
                    self.state.reverse = false;
                }

                38 => {
                    // 设置前景色
                    let (idx, color) = self.t416_color(i);
                    i = idx;
                    if let Some(color) = color {
                        let mut max = color.red.max(color.green);
                        max = max.max(color.blue);

                        let mut hue = 0;
                        if color.red > max / 2 {
                            hue |= 4;
                        }
                        if color.green > max / 2 {
                            hue |= 2;
                        }
                        if color.blue > max / 2 {
                            hue |= 1;
                        }

                        if hue == 7 && max <= 0x55 {
                            hue = 0;
                            self.state.intensity = VirtualConsoleIntensity::Bold;
                        } else if max > 0xaa {
                            self.state.intensity = VirtualConsoleIntensity::Bold;
                        } else {
                            self.state.intensity = VirtualConsoleIntensity::Normal;
                        }

                        self.state.color = (self.state.color & 0xf0) | hue;
                    }
                }

                48 => {
                    // 设置背景色
                    let (idx, color) = self.t416_color(i);
                    i = idx;
                    if let Some(color) = color {
                        self.state.color = (self.state.color & 0x0f)
                            | ((color.red as u8 & 0x80) >> 1)
                            | ((color.green as u8 & 0x80) >> 2)
                            | ((color.blue as u8 & 0x80) >> 3);
                    }
                }

                39 => {
                    // 恢复默认前景色
                    self.state.color = (self.def_color & 0x0f) | (self.state.color & 0xf0);
                }

                49 => {
                    // 恢复默认背景色
                    self.state.color = (self.def_color & 0xf0) | (self.state.color & 0x0f);
                }

                _ => {
                    if self.par[i] >= 90 && self.par[i] <= 107 {
                        if self.par[i] < 100 {
                            self.state.intensity = VirtualConsoleIntensity::Bold;
                        }
                        self.par[i] -= 60;
                    }

                    if self.par[i] >= 30 && self.par[i] <= 37 {
                        self.state.color =
                            COLOR_TABLE[self.par[i] as usize - 30] | self.state.color & 0xf0;
                    } else if self.par[i] >= 40 && self.par[i] <= 47 {
                        self.state.color =
                            (COLOR_TABLE[self.par[i] as usize - 40] << 4) | self.state.color & 0xf0;
                    }
                }
            }

            i += 1;
        }

        self.update_attr();
    }

    /// ##  处理Control Sequence Introducer（控制序列引导符） J字符
    /// 该命令用于擦除终端显示区域的部分或全部内容。根据参数 vpar 的不同值，执行不同的擦除操作：
    /// - vpar 为 0 时，擦除从光标位置到显示区域末尾的内容；
    /// - vpar 为 1 时，擦除从显示区域起始位置到光标位置的内容；
    /// - vpar 为 2 或 3 时，分别表示擦除整个显示区域的内容，其中参数 3 还会清除回滚缓冲区的内容。
    #[allow(non_snake_case)]
    fn csi_J(&mut self, vpar: u32) {
        let count;
        let start;

        match vpar {
            0 => {
                // 擦除从光标位置到显示区域末尾的内容
                count = self.screen_buf.len() - self.pos;
                start = self.pos;
            }
            1 => {
                // 擦除从显示区域起始位置到光标位置的内容
                count = self.pos;
                start = 0;
            }
            2 => {
                // 擦除整个显示区域的内容
                count = self.screen_buf.len();
                start = 0;
            }
            3 => {
                // 表示擦除整个显示区域的内容，还会清除回滚缓冲区的内容
                // TODO:当前未实现回滚缓冲
                count = self.screen_buf.len();
                start = 0;
            }
            _ => {
                return;
            }
        }

        for i in self.screen_buf[start..(start + count)].iter_mut() {
            *i = self.erase_char;
        }

        if self.should_update() {
            self.do_update_region(start, count)
        }

        self.need_wrap = false;
    }

    /// ##  处理Control Sequence Introducer（控制序列引导符） K字符
    /// 该命令用于擦除终端当前行的部分或全部内容。根据参数 vpar 的不同值，执行不同的擦除操作：
    /// - vpar 为 0 时，擦除从光标位置到该行末尾的内容
    /// - vpar 为 1 时，擦除从该行起始位置到光标位置的内容
    /// - vpar 为 2 时，擦除整个行。
    #[allow(non_snake_case)]
    fn csi_K(&mut self, vpar: u32) {
        let count;
        let start;

        match vpar {
            0 => {
                // 擦除从光标位置到该行末尾的内容
                count = self.cols - self.state.x;
                start = self.pos;
            }
            1 => {
                // 擦除从该行起始位置到光标位置的内容
                count = self.state.x + 1;
                start = self.pos - self.state.x;
            }
            2 => {
                // 擦除整个行
                count = self.cols;
                start = self.pos - self.state.x;
            }
            _ => {
                return;
            }
        }

        let max_idx = self.screen_buf.len();
        for i in self.screen_buf[start..max_idx.min(start + count)].iter_mut() {
            *i = self.erase_char;
        }

        if self.should_update() {
            self.do_update_region(start, count.min(max_idx - start))
        }

        self.need_wrap = false;
    }

    fn t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>) {
        idx += 1;
        if idx > self.npar as usize {
            return (idx, None);
        }

        if self.par[idx] == 5 && idx < self.npar as usize {
            // 256色
            idx += 1;
            return (idx, Some(Color::from_256(self.par[idx])));
        } else if self.par[idx] == 2 && idx + 3 <= self.npar as usize {
            // 24位
            let color = Color {
                red: self.par[idx + 1] as u16,
                green: self.par[idx + 2] as u16,
                blue: self.par[idx + 3] as u16,
                ..Default::default()
            };
            idx += 3;
            return (idx, Some(color));
        } else {
            return (idx, None);
        }
    }

    /// ## 处理终端控制字符
    #[inline(never)]
    pub fn do_control(&mut self, ch: u32) {
        // 首先检查是否处于 ANSI 控制字符串状态
        if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) {
            return;
        }

        match ch {
            0 => {
                return;
            }
            7 => {
                // BEL
                if self.vc_state.is_ansi_control_string() {
                    self.vc_state = VirtualConsoleState::ESnormal;
                }
                // TODO: 发出声音？
                return;
            }
            8 => {
                // BS backspace
                self.backspace();
                return;
            }
            9 => {
                // 水平制表符（Horizontal Tab）
                self.pos -= self.state.x;

                self.state.x = self
                    .tab_stop
                    .next_index(self.state.x + 1)
                    .unwrap_or(self.cols - 1);
                self.state.x = core::cmp::min(self.state.x, self.cols - 1);

                self.pos += self.state.x;
                // TODO: notify
                return;
            }
            10..=12 => {
                // LD line feed
                self.line_feed();
                // TODO: 检查键盘模式
                self.carriage_return();
                return;
            }
            13 => {
                // CR 回车符
                self.carriage_return();
                return;
            }
            14 => {
                todo!("Gx_charset todo!");
            }
            15 => {
                todo!("Gx_charset todo!");
            }
            24 | 26 => {
                self.vc_state = VirtualConsoleState::ESnormal;
                return;
            }
            27 => {
                // esc
                self.vc_state = VirtualConsoleState::ESesc;
                return;
            }
            127 => {
                // delete
                self.delete();
                return;
            }
            155 => {
                // '['
                self.vc_state = VirtualConsoleState::ESsquare;
                return;
            }
            _ => {}
        }

        match self.vc_state {
            VirtualConsoleState::ESesc => {
                self.vc_state = VirtualConsoleState::ESnormal;
                match ch as u8 as char {
                    '[' => {
                        self.vc_state = VirtualConsoleState::ESsquare;
                    }
                    ']' => {
                        self.vc_state = VirtualConsoleState::ESnonstd;
                    }
                    '_' => {
                        self.vc_state = VirtualConsoleState::ESapc;
                    }
                    '^' => {
                        self.vc_state = VirtualConsoleState::ESpm;
                    }
                    '%' => {
                        self.vc_state = VirtualConsoleState::ESpercent;
                    }
                    'E' => {
                        self.carriage_return();
                        self.line_feed();
                    }
                    'M' => {
                        self.reverse_index();
                    }
                    'D' => {
                        self.line_feed();
                    }
                    'H' => {
                        if self.state.x < 256 {
                            self.tab_stop.set(self.state.x, true);
                        }
                    }
                    'P' => {
                        self.vc_state = VirtualConsoleState::ESdcs;
                    }
                    'Z' => {
                        todo!("Respond ID todo!");
                    }
                    '7' => self.saved_state = self.state.clone(),
                    '8' => self.restore_cursor(),
                    '(' => {
                        self.vc_state = VirtualConsoleState::ESsetG0;
                    }
                    ')' => {
                        self.vc_state = VirtualConsoleState::ESsetG1;
                    }
                    '#' => {
                        self.vc_state = VirtualConsoleState::EShash;
                    }
                    'c' => {
                        self.reset(true);
                    }
                    '>' => {
                        todo!("clr_kbd todo");
                    }
                    '=' => {
                        todo!("set_kbd todo");
                    }
                    _ => {}
                }
            }
            VirtualConsoleState::ESsquare => {
                for i in self.par.iter_mut() {
                    *i = 0;
                }
                self.vc_state = VirtualConsoleState::ESgetpars;
                self.npar = 0;
                let c = ch as u8 as char;
                if c == '[' {
                    self.vc_state = VirtualConsoleState::ESfunckey;
                    return;
                }

                match c {
                    '?' => {
                        self.private = Vt102_OP::Pdec;
                        return;
                    }
                    '>' => {
                        self.private = Vt102_OP::Pgt;
                        return;
                    }
                    '=' => {
                        self.private = Vt102_OP::Peq;
                        return;
                    }
                    '<' => {
                        self.private = Vt102_OP::Plt;
                        return;
                    }
                    _ => {}
                }

                self.private = Vt102_OP::Pecma;
                self.do_getpars(c);
            }
            VirtualConsoleState::ESgetpars => {
                let c = ch as u8 as char;
                self.do_getpars(c);
            }
            VirtualConsoleState::ESfunckey => {
                self.vc_state = VirtualConsoleState::ESnormal;
                return;
            }
            VirtualConsoleState::EShash => {
                self.vc_state = VirtualConsoleState::ESnormal;
                if ch as u8 as char == '8' {
                    self.erase_char = (self.erase_char & 0xff00) | 'E' as u16;
                    self.csi_J(2);
                    self.erase_char = (self.erase_char & 0xff00) | ' ' as u16;
                    self.do_update_region(0, self.screen_buf.len());
                }
                return;
            }
            VirtualConsoleState::ESsetG0 => {
                todo!("SetGx todo");
            }
            VirtualConsoleState::ESsetG1 => {
                todo!("SetGx todo");
            }
            VirtualConsoleState::ESpercent => {
                self.vc_state = VirtualConsoleState::ESnormal;
                let c = ch as u8 as char;
                match c {
                    '@' => {
                        self.utf = false;
                        return;
                    }
                    'G' | '8' => {
                        self.utf = true;
                        return;
                    }
                    _ => {}
                }
                return;
            }
            VirtualConsoleState::EScsiignore => {
                if (20..=0x3f).contains(&ch) {
                    return;
                }
                self.vc_state = VirtualConsoleState::ESnormal;
                return;
            }
            VirtualConsoleState::ESnonstd => {
                let c = ch as u8 as char;
                if c == 'P' {
                    for i in self.par.iter_mut() {
                        *i = 0;
                    }
                    self.npar = 0;
                    self.vc_state = VirtualConsoleState::ESpalette;
                    return;
                } else if c == 'R' {
                    self.reset_palette();
                    self.vc_state = VirtualConsoleState::ESnormal;
                } else if c.is_ascii_digit() {
                    self.vc_state = VirtualConsoleState::ESosc;
                } else {
                    self.vc_state = VirtualConsoleState::ESnormal;
                }
            }
            VirtualConsoleState::ESpalette => {
                let c = ch as u8 as char;
                if c.is_ascii_hexdigit() {
                    self.npar += 1;
                    self.par[self.npar as usize] = c.to_digit(16).unwrap();

                    if self.npar == 7 {
                        let mut i = self.par[0] as usize;
                        let mut j = 0;
                        self.palette[i].red = self.par[j] as u16;
                        j += 1;
                        self.palette[i].green = self.par[j] as u16;
                        j += 1;
                        self.palette[i].blue = self.par[j] as u16;
                        j += 1;
                        i += 1;
                        self.palette[i].red = self.par[j] as u16;
                        j += 1;
                        self.palette[i].green = self.par[j] as u16;
                        j += 1;
                        self.palette[i].blue = self.par[j] as u16;
                        self.set_palette();
                        self.vc_state = VirtualConsoleState::ESnormal;
                    }
                }
            }
            VirtualConsoleState::ESosc => {}
            VirtualConsoleState::ESapc => {}
            VirtualConsoleState::ESpm => {}
            VirtualConsoleState::ESdcs => {}
            VirtualConsoleState::ESnormal => {}
        }
    }

    #[inline(never)]
    pub fn console_write_normal(&mut self, mut tc: u32, c: u32, draw: &mut DrawRegion) -> bool {
        let mut attr = self.attr;
        let himask = self.hi_font_mask;
        let charmask = if himask == 0 { 0xff } else { 0x1ff };
        let mut width = 1;
        // 表示需不需要反转
        let mut invert = false;
        if self.utf && !self.display_ctrl && FontDesc::is_double_width(c) {
            width = 2;
        }

        let tmp = self.unicode_to_index(tc);
        if tmp & (!charmask as i32) != 0 {
            if tmp == -1 || tmp == -2 {
                return false;
            }

            // 未找到
            if (!self.utf || self.display_ctrl || c < 128) && (c & !charmask) == 0 {
                tc = c;
            } else {
                let tmp = self.unicode_to_index(0xfffd);
                if tmp < 0 {
                    invert = true;
                    let tmp = self.unicode_to_index('?' as u32);
                    if tmp < 0 {
                        tc = '?' as u32;
                    } else {
                        tc = tmp as u32;
                    }

                    attr = self.invert_attr();
                    self.flush(draw);
                }
            }
        }

        loop {
            if self.need_wrap || self.insert_mode {
                self.flush(draw);
            }
            if self.need_wrap {
                self.carriage_return();
                self.line_feed();
            }

            if self.insert_mode {
                self.insert_char(1);
            }

            // TODO: 处理unicode screen buf

            if himask != 0 {
                tc = (if (tc & 0x100) != 0 { himask as u32 } else { 0 }) | (tc & 0xff);
            }

            tc |= ((attr as u32) << 8) & (!himask as u32);

            // warn!(
            //     "ch {} pos {} x {} y {} cols {}",
            //     c as u8 as char,
            //     self.pos,
            //     self.state.x,
            //     self.state.y,
            //     self.cols,
            // );
            self.screen_buf[self.pos] = tc as u16;

            if self.should_update() && draw.x.is_none() {
                // 设置draw参数
                draw.x = Some(self.state.x as u32);
                draw.offset = self.pos;
            }

            if self.state.x == self.cols - 1 {
                // 需要换行？
                self.need_wrap = self.autowrap;
                draw.size += 1;
            } else {
                self.state.x += 1;
                self.pos += 1;
                draw.size += 1;
            }

            width -= 1;
            if width <= 0 {
                break;
            }
            let tmp = self.unicode_to_index(' ' as u32);
            tc = if tmp < 0 { ' ' as u32 } else { tmp as u32 };
        }

        if invert {
            self.flush(draw);
        }
        true
    }

    /// ## 当前vc插入nr个字符
    fn insert_char(&mut self, nr: usize) {
        // TODO: 管理unicode屏幕信息

        let pos = self.pos;
        // 把当前位置以后得字符向后移动nr*2位
        self.screen_buf[pos..].rotate_right(nr * 2);

        // 把空出来的位置用erase_char填充
        for c in &mut self.screen_buf[pos..(pos + nr * 2)] {
            *c = self.erase_char
        }

        self.need_wrap = false;

        // 更新本行后面部分
        self.do_update_region(self.pos, self.cols - self.state.x);
    }

    /// ## 更新虚拟控制台指定区域的显示
    fn do_update_region(&self, mut start: usize, mut count: usize) {
        let ret = self.driver_funcs().con_getxy(self, start);
        let (mut x, mut y) = if let Ok((_, tmp_x, tmp_y)) = ret {
            // start = tmp_start;
            (tmp_x, tmp_y)
        } else {
            (start % self.cols, start / self.cols)
        };

        loop {
            // 记录当前字符的属性
            let mut attr = self.screen_buf[start] & 0xff00;
            let mut startx = x;
            let mut size = 0;

            while count != 0 && x < self.cols {
                // 检查属性是否变化，如果属性变了，则将前一个字符先输出
                if attr != (self.screen_buf[start] & 0xff00) && size > 0 {
                    let _ = self.driver_funcs().con_putcs(
                        self,
                        &self.screen_buf[start..],
                        size,
                        y as u32,
                        startx as u32,
                    );
                    startx = x;
                    start += size;
                    size = 0;
                    attr = self.screen_buf[start] & 0xff00;
                }
                size += 1;
                x += 1;
                count -= 1;
            }

            if size > 0 {
                let _ = self.driver_funcs().con_putcs(
                    self,
                    &self.screen_buf[start..],
                    size,
                    y as u32,
                    startx as u32,
                );
            }
            if count == 0 {
                break;
            }

            // 一行
            x = 0;
            y += 1;

            let ret = self.driver_funcs().con_getxy(self, start);
            if let Ok(ret) = ret {
                start = ret.0;
            } else {
                return;
            }
        }
    }

    const UNI_DIRECT_MAKS: u32 = 0x01ff;
    const UNI_DIRECT_BASE: u32 = 0xf000;
    /// ## unicode字符转对应的坐标，暂时这样写，还没有适配unicode
    /// 这里是糊代码的，后面重写
    fn unicode_to_index(&self, ch: u32) -> i32 {
        if ch > 0xfff {
            // 未找到
            return -4;
        } else if ch < 0x20 {
            // 不可打印
            return -1;
        } else if ch == 0xfeff || (0x200b..=0x200f).contains(&ch) {
            // 零长空格
            return -2;
        } else if (ch & !Self::UNI_DIRECT_MAKS) == Self::UNI_DIRECT_BASE {
            return (ch & Self::UNI_DIRECT_MAKS) as i32;
        }

        // TODO: 暂时这样写，表示不支持
        return -3;
    }

    fn invert_attr(&self) -> u8 {
        if !self.color_mode {
            return self.attr ^ 0x08;
        }

        if self.hi_font_mask == 0x100 {
            return (self.attr & 0x11) | ((self.attr & 0xe0) >> 4) | ((self.attr & 0x0e) << 4);
        }

        return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4);
    }

    pub fn flush(&self, draw: &mut DrawRegion) {
        if draw.x.is_none() {
            return;
        }

        let _ = self.driver_funcs().con_putcs(
            self,
            &self.screen_buf[draw.offset..draw.offset + draw.size],
            draw.size,
            self.state.y as u32,
            draw.x.unwrap(),
        );

        draw.x = None;
        draw.size = 0;
    }

    #[allow(clippy::manual_rotate)]
    fn build_attr(
        &self,
        color: u8,
        intensity: VirtualConsoleIntensity,
        blink: bool,
        underline: bool,
        reverse: bool,
        italic: bool,
    ) -> u8 {
        let ret = self
            .driver_funcs()
            .con_build_attr(self, color, intensity, blink, underline, reverse, italic);

        if let Ok(ret) = ret {
            return ret;
        }

        let mut ret = color;

        if !self.color_mode {
            return intensity as u8
                | (italic as u8) << 1
                | (underline as u8) << 2
                | (reverse as u8) << 3
                | (blink as u8) << 7;
        }

        if italic {
            ret = (ret & 0xf0) | self.italic_color as u8;
        } else if underline {
            ret = (ret & 0xf0) | self.underline_color as u8;
        } else if intensity == VirtualConsoleIntensity::HalfBright {
            ret = (ret & 0xf0) | self.half_color as u8;
        }

        if reverse {
            ret = (ret & 0x88) | (((ret >> 4) | (ret << 4)) & 0x77);
        }

        if blink {
            ret ^= 0x80;
        }

        if intensity == VirtualConsoleIntensity::Bold {
            ret ^= 0x08;
        }

        if self.hi_font_mask == 0x100 {
            ret <<= 1;
        }

        ret
    }

    pub(super) fn update_attr(&mut self) {
        self.attr = self.build_attr(
            self.state.color,
            self.state.intensity,
            self.state.blink,
            self.state.underline,
            self.state.reverse ^ self.screen_mode,
            self.state.italic,
        );

        self.erase_char = ' ' as u16
            | ((self.build_attr(
                self.state.color,
                VirtualConsoleIntensity::Normal,
                self.state.blink,
                false,
                self.screen_mode,
                false,
            ) as u16)
                << 8);
    }

    fn default_attr(&mut self) {
        self.state.intensity = VirtualConsoleIntensity::Normal;
        self.state.italic = false;
        self.state.underline = false;
        self.state.reverse = false;
        self.state.blink = false;
        self.state.color = self.def_color;
    }
}

/// ## 虚拟控制台的状态信息
#[derive(Debug, Default, Clone)]
pub struct VirtualConsoleInfo {
    // x,y表示光标坐标
    pub x: usize,
    pub y: usize,
    pub color: u8,

    /// 表示字符的强度
    intensity: VirtualConsoleIntensity,
    /// 斜体
    italic: bool,
    /// 下划线
    underline: bool,
    /// 字符闪烁
    blink: bool,
    /// 前景与背景色反转
    reverse: bool,
}

impl VirtualConsoleInfo {
    pub fn new(x: usize, y: usize) -> Self {
        Self {
            x,
            y,
            color: Default::default(),
            intensity: Default::default(),
            italic: Default::default(),
            underline: Default::default(),
            blink: Default::default(),
            reverse: Default::default(),
        }
    }
}

/// 字符强度
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum VirtualConsoleIntensity {
    /// 暗淡
    HalfBright = 0,
    /// 正常
    Normal = 1,
    /// 粗体
    Bold = 2,
}

impl Default for VirtualConsoleIntensity {
    fn default() -> Self {
        Self::Normal
    }
}

/// ## 虚拟控制台的状态
///
/// 可以把VC的接收字符理解为一个状态机
#[derive(Debug, PartialEq, Clone)]
pub enum VirtualConsoleState {
    /// 正常状态
    ESnormal,
    /// 收到了转义字符 \e，即"Escape"字符
    ESesc,
    /// 收到了 "[" 字符，通常是 ANSI 控制序列的开始
    ESsquare,
    /// 解析参数状态
    ESgetpars,
    /// 功能键状态
    ESfunckey,
    /// 收到了 "#" 字符
    EShash,
    /// 设置 G0 字符集状态
    ESsetG0,
    /// 设置 G1 字符集状态
    ESsetG1,
    /// 收到了 "%" 字符
    ESpercent,
    /// 忽略 ANSI 控制序列状态
    EScsiignore,
    /// 非标准字符状态
    ESnonstd,
    /// 调色板状态
    ESpalette,
    /// Operating System Command (OSC) 状态
    ESosc,
    ///  Application Program Command (APC) 状态
    ESapc,
    /// Privacy Message (PM) 状态
    ESpm,
    /// Device Control String (DCS) 状态
    ESdcs,
}

impl VirtualConsoleState {
    pub fn is_ansi_control_string(&self) -> bool {
        if *self == Self::ESosc
            || *self == Self::ESapc
            || *self == Self::ESpm
            || *self == Self::ESdcs
        {
            return true;
        }

        false
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[allow(non_camel_case_types)]
pub enum Vt102_OP {
    Pecma,
    Pdec,
    Peq,
    Pgt,
    Plt,
}

bitflags! {
    #[derive(Default)]
    pub struct VcCursor: u32 {
        /// 默认
        const CUR_DEF			=       0;
        /// 无光标
        const CUR_NONE			=       1;
        /// 下划线形式
        const CUR_UNDERLINE		=	    2;
        /// 光标占据底部的三分之一
        const CUR_LOWER_THIRD	=	    3;
        /// 光标占据底部的一半
        const CUR_LOWER_HALF	=       4;
        ///  光标占据底部的三分之二
        const CUR_TWO_THIRDS	=       5;
        /// 光标为块状（方块）形式
        const CUR_BLOCK			=       6;
        /// 光标属性，用于指示软件光标
        const CUR_SW			=	0x000010;
        /// 光标属性，用于指示光标是否始终在背景上显示
        const CUR_ALWAYS_BG		=	0x000020;
        /// 光标属性，用于指示前景和背景是否反转
        const CUR_INVERT_FG_BG	=	0x000040;
        /// 光标前景色属性，用于指定光标的前景色
        const CUR_FG			=	0x000700;
        /// 光标背景色属性，用于指定光标的背景色
        const CUR_BG			=	0x007000;
    }
}

impl VcCursor {
    pub fn make_cursor(size: u32, change: u32, set: u32) -> Self {
        unsafe { Self::from_bits_unchecked(size | (change << 8) | (set << 16)) }
    }

    pub fn cursor_size(&self) -> Self {
        Self::from_bits_truncate(self.bits & 0x00000f)
    }

    pub fn cursor_set(&self) -> u32 {
        (self.bits & 0xff0000) >> 8
    }

    pub fn cursor_change(&self) -> u32 {
        self.bits & 0x00ff00
    }
}

#[derive(Debug, PartialEq)]
#[allow(dead_code)]
pub enum CursorOperation {
    Draw,
    Erase,
    Move,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ScrollDir {
    Up,
    Down,
}
