use core::{
    fmt::{self, Debug},
    sync::atomic::{AtomicBool, AtomicUsize, Ordering},
};

use alloc::{
    string::String,
    sync::{Arc, Weak},
};
use system_error::SystemError;

use crate::{
    arch::ipc::signal::Signal,
    driver::base::device::device_number::DeviceNumber,
    filesystem::epoll::{
        event_poll::{EPollItemList, EventPoll},
        EPollEventType, EPollItem,
    },
    filesystem::vfs::fasync::{FAsyncItem, FAsyncItems},
    libs::{
        rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
        rwsem::{RwSem, RwSemReadGuard, RwSemWriteGuard},
        spinlock::{SpinLock, SpinLockGuard},
        wait_queue::{EventWaitQueue, WaitQueue},
    },
    mm::VirtAddr,
    process::{pid::Pid, ProcessControlBlock, ProcessManager},
    syscall::user_access::{UserBufferReader, UserBufferWriter},
};

use super::{
    termios::{ControlMode, PosixTermio, PosixTermios, Termios, TtySetTermiosOpt, WindowSize},
    tty_driver::{TtyCorePrivateField, TtyDriver, TtyDriverSubType, TtyDriverType, TtyOperation},
    tty_job_control::TtyJobCtrlManager,
    tty_ldisc::{
        ntty::{NTtyData, NTtyLinediscipline},
        TtyLdiscDrainResult, TtyLineDiscipline,
    },
    tty_port::TtyPort,
    virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, DrawRegion},
};

#[derive(Debug)]
pub struct TtyCore {
    core: TtyCoreData,
    /// 线路规程函数集
    line_discipline: Arc<dyn TtyLineDiscipline>,
}

pub struct TtySleepLock {
    locked: AtomicBool,
    wait_queue: WaitQueue,
}

impl Debug for TtySleepLock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("TtySleepLock")
            .field("locked", &self.locked.load(Ordering::Relaxed))
            .finish()
    }
}

pub struct TtySleepLockGuard<'a> {
    lock: &'a TtySleepLock,
}

impl !Send for TtySleepLockGuard<'_> {}

impl TtySleepLock {
    pub const fn new() -> Self {
        Self {
            locked: AtomicBool::new(false),
            wait_queue: WaitQueue::default(),
        }
    }

    pub fn lock(&self) -> TtySleepLockGuard<'_> {
        if let Some(guard) = self.try_lock() {
            return guard;
        }

        self.wait_queue.wait_until(|| self.try_lock())
    }

    pub fn lock_interruptible(&self, nonblock: bool) -> Result<TtySleepLockGuard<'_>, SystemError> {
        if let Some(guard) = self.try_lock() {
            return Ok(guard);
        }

        if nonblock {
            return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
        }

        self.wait_queue.wait_until_interruptible(|| self.try_lock())
    }

    pub fn is_locked(&self) -> bool {
        self.locked.load(Ordering::Acquire)
    }

    pub fn try_lock(&self) -> Option<TtySleepLockGuard<'_>> {
        if self
            .locked
            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
            .is_ok()
        {
            Some(TtySleepLockGuard { lock: self })
        } else {
            None
        }
    }

    fn unlock(&self) {
        self.locked.store(false, Ordering::Release);
        self.wait_queue.wake_one();
    }
}

impl Drop for TtySleepLockGuard<'_> {
    fn drop(&mut self) {
        self.lock.unlock();
    }
}

impl TtyCore {
    #[inline(never)]
    pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
        let name = driver.tty_line_name(index);
        let device_number = driver
            .device_number(index)
            .expect("Get tty device number failed.");
        let termios = driver.init_termios();
        let core = TtyCoreData {
            tty_driver: driver,
            termios: RwLock::new(termios),
            termios_rwsem: RwSem::new(()),
            name,
            flags: RwLock::new(TtyFlag::empty()),
            count: AtomicUsize::new(0),
            window_size: RwLock::new(WindowSize::default()),
            read_wq: EventWaitQueue::new(),
            write_wq: EventWaitQueue::new(),
            write_lock: TtySleepLock::new(),
            open_close_lock: TtySleepLock::new(),
            open_files: AtomicUsize::new(0),
            job_control_lock: TtySleepLock::new(),
            port: RwLock::new(None),
            index,
            vc_index: AtomicUsize::new(usize::MAX),
            ctrl: SpinLock::new(TtyControlInfo::default()),
            closing: AtomicBool::new(false),
            hangup_generation: AtomicUsize::new(0),
            flow: SpinLock::new(TtyFlowState::default()),
            link: RwLock::default(),
            epitems: EPollItemList::default(),
            fasync_items: FAsyncItems::new(),
            device_number,
            privete_fields: SpinLock::new(None),
        };
        return Arc::new(Self {
            core,
            line_discipline: Arc::new(NTtyLinediscipline {
                data: SpinLock::new(NTtyData::new()),
                output_lock: TtySleepLock::new(),
            }),
        });
    }

    #[inline]
    pub fn core(&self) -> &TtyCoreData {
        return &self.core;
    }

    pub fn private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>> {
        self.core.privete_fields.lock().clone()
    }

    pub fn set_private_fields(&self, fields: Arc<dyn TtyCorePrivateField>) {
        *self.core.privete_fields.lock() = Some(fields);
    }

    #[inline]
    pub fn ldisc(&self) -> Arc<dyn TtyLineDiscipline> {
        self.line_discipline.clone()
    }

    pub fn write_to_core(&self, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
        self.core
            .driver()
            .driver_funcs()
            .write(self.core(), buf, nr)
    }

    pub fn reopen(&self) -> Result<(), SystemError> {
        let tty_core = self.core();
        let driver = tty_core.driver();

        if driver.tty_driver_type() == TtyDriverType::Pty
            && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster
        {
            return Err(SystemError::EIO);
        }

        // if *tty_core.count.read() == 0 {
        //     return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
        // }

        // TODO 判断flags

        tty_core.add_count();

        Ok(())
    }

    #[inline]
    pub fn set_port(&self, port: Arc<dyn TtyPort>) {
        *self.core.port.write() = Some(port);
    }

    fn tty_start_locked(&self, flow: &mut TtyFlowState) -> bool {
        if !flow.stopped || flow.tco_stopped {
            return false;
        }

        flow.stopped = false;
        let _ = self.start(self.core());
        true
    }

    fn tty_stop_locked(&self, flow: &mut TtyFlowState) -> bool {
        if flow.stopped {
            return false;
        }

        flow.stopped = true;
        let _ = self.stop(self.core());
        true
    }

    pub fn tty_start(&self) {
        let mut flow = self.core.flow.lock_irqsave();
        flow.transition_seq = flow.transition_seq.wrapping_add(1);
        if !self.tty_start_locked(&mut flow) {
            return;
        }
        drop(flow);
        self.tty_wakeup();
    }

    /// Starts output without waking writers or invoking the line discipline.
    ///
    /// A caller that observes `true` must call [`Self::tty_wakeup`] after
    /// releasing any line-discipline locks it holds.
    pub(crate) fn tty_start_without_wakeup(&self) -> bool {
        let mut flow = self.core.flow.lock_irqsave();
        flow.transition_seq = flow.transition_seq.wrapping_add(1);
        self.tty_start_locked(&mut flow)
    }

    pub fn tty_stop(&self) {
        let mut flow = self.core.flow.lock_irqsave();
        flow.transition_seq = flow.transition_seq.wrapping_add(1);
        self.tty_stop_locked(&mut flow);
    }

    pub fn tty_stop_tco(&self) {
        let mut flow = self.core.flow.lock_irqsave();
        if flow.tco_stopped {
            return;
        }
        flow.tco_stopped = true;
        flow.transition_seq = flow.transition_seq.wrapping_add(1);
        self.tty_stop_locked(&mut flow);
    }

    pub fn tty_start_tco(&self) {
        let mut flow = self.core.flow.lock_irqsave();
        if !flow.tco_stopped {
            return;
        }
        flow.tco_stopped = false;
        flow.transition_seq = flow.transition_seq.wrapping_add(1);
        if !self.tty_start_locked(&mut flow) {
            return;
        }
        drop(flow);
        self.tty_wakeup();
    }

    /// Send a software flow-control character without output post-processing.
    pub fn tty_send_xchar(&self, ch: u8) -> Result<(), SystemError> {
        let hook_result = {
            let _termios_guard = self.core.termios_read_lock();
            self.core
                .tty_driver
                .driver_funcs()
                .send_xchar(self.core(), ch)
        };
        if hook_result != Err(SystemError::ENOSYS) {
            // Linux's send_xchar hook is void: an implemented driver path is
            // best-effort and never exposes a device error to userspace.
            return Ok(());
        }

        let _write_guard = self.core.write_lock().lock_interruptible(false)?;
        let _termios_guard = self.core.termios_read_lock();

        let (temporarily_started, transition_seq) = {
            let mut flow = self.core.flow.lock_irqsave();
            let transition_seq = flow.transition_seq;
            let temporarily_started = self.tty_start_locked(&mut flow);
            (temporarily_started, transition_seq)
        };
        let _ = self.write(self.core(), &[ch], 1);
        let mut should_wake = false;
        if temporarily_started {
            let mut flow = self.core.flow.lock_irqsave();
            // A concurrent flow-control request owns the final state. Restore
            // the temporary stop only if no request raced with this fallback.
            if flow.transition_seq == transition_seq && !flow.stopped {
                self.tty_stop_locked(&mut flow);
            } else if !flow.stopped {
                // A start request can observe the temporary running state and
                // skip its own wakeup. Complete that request after dropping
                // every lock that write_wakeup may re-enter.
                should_wake = true;
            }
        }
        drop(_termios_guard);
        drop(_write_guard);
        if should_wake {
            self.tty_wakeup();
        }
        Ok(())
    }

    pub(crate) fn reset_flow_state(&self) {
        *self.core.flow.lock_irqsave() = TtyFlowState::default();
    }

    pub fn tty_wakeup(&self) {
        if self.core.flags().contains(TtyFlag::DO_WRITE_WAKEUP) {
            let _ = self.ldisc().write_wakeup(self);
        }

        let events = EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
        self.core().write_wq.wakeup_any(events.bits() as u64);
        let _ = EventPoll::wakeup_epoll(self.core().epitems(), events);
    }

    pub fn tty_vhangup(tty: Arc<TtyCore>) {
        let _job_control_guard = tty.core().job_control_lock().lock();
        {
            let mut flags = tty.core().flags_write();
            if flags.intersects(TtyFlag::HUPPED | TtyFlag::HUPPING) {
                return;
            }
            flags.insert(TtyFlag::HUPPING);
            tty.core().hangup_generation.fetch_add(1, Ordering::AcqRel);
        }
        // Linux removes fasync registrations before replacing existing tty
        // file operations with hung_up_tty_fops. This also clears O_ASYNC on
        // every pre-hangup open file description.
        tty.core().fasync_items.clear();

        let pgid = TtyJobCtrlManager::remove_session_tty_job_locked(&tty, None);

        if let Some(pgrp) = pgid {
            let _ = crate::ipc::kill::send_signal_to_pgid(&pgrp, Signal::SIGHUP);
            let _ = crate::ipc::kill::send_signal_to_pgid(&pgrp, Signal::SIGCONT);
        }

        let _ = tty.ldisc().hangup(tty.clone());

        {
            let mut ctrl = tty.core().contorl_info_irqsave();
            ctrl.pktstatus = TtyPacketStatus::empty();
        }

        {
            let mut flags = tty.core().flags_write();
            flags.remove(TtyFlag::DO_WRITE_WAKEUP);
            flags.remove(TtyFlag::HUPPING);
            flags.insert(TtyFlag::HUPPED);
        }

        tty.core().read_wq().wakeup_all();
        tty.core().write_wq().wakeup_all();
        let _ = EventPoll::wakeup_epoll(tty.core().epitems(), EPollEventType::EPOLLHUP);
    }

    pub fn tty_mode_ioctl(tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<usize, SystemError> {
        let core = tty.core();
        let redirected_from_pty_master = core.driver().tty_driver_type() == TtyDriverType::Pty
            && core.driver().tty_driver_sub_type() == TtyDriverSubType::PtyMaster;
        let real_tty = if redirected_from_pty_master {
            core.link().unwrap()
        } else {
            tty
        };
        match cmd {
            TtyIoctlCmd::TCGETS => {
                let snapshot = real_tty.core.committed_termios_snapshot();
                let termios = PosixTermios::from_kernel_termios(&snapshot);
                let mut user_writer = UserBufferWriter::new(
                    VirtAddr::new(arg).as_ptr::<PosixTermios>(),
                    core::mem::size_of::<PosixTermios>(),
                    true,
                )?;

                user_writer.copy_one_to_user(&termios, 0)?;
                return Ok(0);
            }
            TtyIoctlCmd::TCGETA => {
                let snapshot = real_tty.core.committed_termios_snapshot();
                let termio = PosixTermio::from_kernel_termios(&snapshot);
                let mut user_writer = UserBufferWriter::new(
                    VirtAddr::new(arg).as_ptr::<PosixTermio>(),
                    core::mem::size_of::<PosixTermio>(),
                    true,
                )?;
                user_writer.copy_one_to_user(&termio, 0)?;
                return Ok(0);
            }
            TtyIoctlCmd::TCSETS => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_OLD,
                    redirected_from_pty_master,
                );
            }
            TtyIoctlCmd::TCSETSW => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_OLD,
                    redirected_from_pty_master,
                );
            }
            TtyIoctlCmd::TCSETSF => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_FLUSH
                        | TtySetTermiosOpt::TERMIOS_WAIT
                        | TtySetTermiosOpt::TERMIOS_OLD,
                    redirected_from_pty_master,
                );
            }
            TtyIoctlCmd::TCSETA => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_TERMIO,
                    redirected_from_pty_master,
                );
            }
            TtyIoctlCmd::TCSETAW => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_TERMIO,
                    redirected_from_pty_master,
                );
            }
            TtyIoctlCmd::TCSETAF => {
                return TtyCore::core_set_termios(
                    real_tty,
                    VirtAddr::new(arg),
                    TtySetTermiosOpt::TERMIOS_FLUSH
                        | TtySetTermiosOpt::TERMIOS_WAIT
                        | TtySetTermiosOpt::TERMIOS_TERMIO,
                    redirected_from_pty_master,
                );
            }
            _ => {
                return Err(SystemError::ENOIOCTLCMD);
            }
        }
    }

    pub fn tty_perform_flush(tty: Arc<TtyCore>, arg: usize) -> Result<usize, SystemError> {
        // Job control check for TCFLSH ioctl.  This is a separate path
        // from core_set_termios (termios ioctls); the two are never
        // invoked concurrently for the same operation.
        TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;

        match arg {
            TtyFlushArg::TCIFLUSH => {
                tty.ldisc().flush_buffer(tty.clone())?;
            }
            TtyFlushArg::TCIOFLUSH => {
                tty.ldisc().flush_buffer(tty.clone())?;
                tty.ldisc().flush_output(tty.clone())?;
            }
            TtyFlushArg::TCOFLUSH => {
                tty.ldisc().flush_output(tty.clone())?;
            }
            _ => {
                return Err(SystemError::EINVAL);
            }
        }

        Ok(0)
    }

    pub fn core_set_termios(
        tty: Arc<TtyCore>,
        arg: VirtAddr,
        opt: TtySetTermiosOpt,
        redirected_from_pty_master: bool,
    ) -> Result<usize, SystemError> {
        // Check job control: prevent background process groups from changing
        // terminal attributes without permission.  Matches Linux 6.6
        // set_termios() which calls tty_check_change() before any work.
        // This path is separate from tty_perform_flush (TCFLSH ioctl);
        // the two never overlap in a single operation.
        TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;

        #[allow(unused_assignments)]
        // TERMIOS_TERMIO下会用到
        let mut tmp_termios = tty.core().committed_termios_snapshot();

        if opt.contains(TtySetTermiosOpt::TERMIOS_TERMIO) {
            let user_reader = UserBufferReader::new(
                arg.as_ptr::<PosixTermio>(),
                core::mem::size_of::<PosixTermio>(),
                true,
            )?;
            let mut termio = PosixTermio::default();
            user_reader.copy_one_from_user(&mut termio, 0)?;
            tmp_termios = termio.to_kernel_termios(&tmp_termios);
        } else {
            let user_reader = UserBufferReader::new(
                arg.as_ptr::<PosixTermios>(),
                core::mem::size_of::<PosixTermios>(),
                true,
            )?;

            let mut term = PosixTermios::default();
            user_reader.copy_one_from_user(&mut term, 0)?;

            tmp_termios = term.to_kernel_termios();
        }

        if opt.intersects(TtySetTermiosOpt::TERMIOS_WAIT | TtySetTermiosOpt::TERMIOS_FLUSH) {
            let events = (EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM).bits() as u64;

            loop {
                let write_guard = tty.core().write_lock().lock_interruptible(false)?;
                let termios_guard = tty.core().termios_write_lock_interruptible()?;

                let output_closed = Self::output_terminal_closed(tty.core());
                if output_closed && !redirected_from_pty_master {
                    return Err(SystemError::EIO);
                }

                if !output_closed {
                    match tty.ldisc().drain_output(tty.clone())? {
                        TtyLdiscDrainResult::Drained => {}
                        TtyLdiscDrainResult::NeedWriteRoom(required) => {
                            let required = required.max(1);
                            drop(termios_guard);
                            drop(write_guard);
                            tty.core().write_wq().wait_event_interruptible(events, || {
                                Self::output_terminal_closed(tty.core())
                                    || tty.write_room(tty.core()) >= required
                                    || !tty.ldisc().output_pending()
                            })?;
                            if Self::output_terminal_closed(tty.core())
                                && !redirected_from_pty_master
                            {
                                return Err(SystemError::EIO);
                            }
                            continue;
                        }
                    }

                    if tty.chars_in_buffer(tty.core()) != 0 {
                        drop(termios_guard);
                        drop(write_guard);
                        tty.core().write_wq().wait_event_interruptible(events, || {
                            Self::output_terminal_closed(tty.core())
                                || tty.chars_in_buffer(tty.core()) == 0
                        })?;
                        if Self::output_terminal_closed(tty.core()) && !redirected_from_pty_master {
                            return Err(SystemError::EIO);
                        }
                        continue;
                    }
                }

                // Linux flushes input and waits for the physical transmitter
                // before tty_set_termios() takes termios_rwsem for the short
                // attribute transaction. Keeping the write side of the
                // semaphore across either operation can deadlock synchronous
                // input producers and unnecessarily stalls RX at low baud.
                drop(termios_guard);

                // Linux performs input flush after the output-drain recheck.
                if opt.contains(TtySetTermiosOpt::TERMIOS_FLUSH) {
                    tty.ldisc().flush_buffer(tty.clone())?;
                }

                if opt.contains(TtySetTermiosOpt::TERMIOS_WAIT) && !output_closed {
                    tty.wait_until_sent(tty.core())?;
                    let current = ProcessManager::current_pcb();
                    if current.has_pending_signal_fast() && current.has_pending_not_masked_signal()
                    {
                        return Err(SystemError::ERESTARTSYS);
                    }
                    if Self::output_terminal_closed(tty.core()) && !redirected_from_pty_master {
                        return Err(SystemError::EIO);
                    }
                }

                let termios_guard = tty.core().termios_write_lock_interruptible()?;
                let result = Self::set_termios_locked(tty.clone(), tmp_termios);
                drop(termios_guard);
                drop(write_guard);
                Self::retry_deferred_output(&tty);
                result?;
                return Ok(0);
            }
        }

        Self::set_termios_next(tty, tmp_termios)?;
        Ok(0)
    }

    fn set_termios_next(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
        let termios_guard = tty.core().termios_write_lock_interruptible()?;
        let result = Self::set_termios_locked(tty.clone(), new_termios);
        drop(termios_guard);
        Self::retry_deferred_output(&tty);
        result
    }

    /// Apply termios while the caller holds `termios_write_lock_interruptible()`.
    fn set_termios_locked(tty: Arc<TtyCore>, new_termios: Termios) -> Result<(), SystemError> {
        let mut termios = tty.core().termios_write();

        let old_termios = *termios;
        *termios = new_termios;
        let tmp = termios.control_mode;
        termios.control_mode ^= (tmp ^ old_termios.control_mode) & ControlMode::ADDRB;

        drop(termios);
        let ret = tty.set_termios(tty.clone(), old_termios);
        let mut termios = tty.core().termios_write();
        if ret.is_err() {
            termios.control_mode &= ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL;
            termios.control_mode |= old_termios.control_mode
                & !(ControlMode::HUPCL | ControlMode::CREAD | ControlMode::CLOCAL);
            termios.input_speed = old_termios.input_speed;
            termios.output_speed = old_termios.output_speed;
        }

        drop(termios);
        let ld = tty.ldisc();
        ld.set_termios(tty, Some(old_termios)).ok();

        Ok(())
    }

    fn output_terminal_closed(core: &TtyCoreData) -> bool {
        let flags = core.flags();
        flags.intersects(TtyFlag::IO_ERROR | TtyFlag::HUPPED | TtyFlag::HUPPING)
            || (flags.contains(TtyFlag::OTHER_CLOSED)
                && core.driver().tty_driver_sub_type() != TtyDriverSubType::PtyMaster)
    }

    fn retry_deferred_output(tty: &Arc<TtyCore>) {
        if tty.core().flags().contains(TtyFlag::DO_WRITE_WAKEUP) {
            tty.tty_wakeup();
        }
    }

    pub fn tty_do_resize(&self, windowsize: WindowSize) -> Result<(), SystemError> {
        // TODO: 向前台进程发送信号
        *self.core.window_size_write() = windowsize;
        Ok(())
    }
}

#[derive(Debug, Default)]
pub struct TtyControlInfo {
    /// 当前会话的SId
    pub session: Option<Arc<Pid>>,
    /// 前台进程组id
    pub pgid: Option<Arc<Pid>>,

    /// packet模式下使用，目前未用到
    pub pktstatus: TtyPacketStatus,
    pub packet: bool,
}

impl TtyControlInfo {
    pub fn set_info_by_pcb(&mut self, pcb: Arc<ProcessControlBlock>) {
        self.session = pcb.task_session();
        self.pgid = pcb.task_pgrp();
    }

    /// 清除当前session的pid
    ///
    /// 如果当前session已经死了，则将其清除。
    pub fn clear_dead_session(&mut self) {
        if self.session.is_none() {
            return;
        }

        let clean = self.session.as_ref().map(|s| s.dead()).unwrap();
        if clean {
            self.session = None;
        }
    }
}

#[derive(Debug, Default)]
pub struct TtyFlowState {
    /// 表示流控是否被停止
    pub stopped: bool,
    /// 表示 TCO（Transmit Continuous Operation）流控是否被停止
    pub tco_stopped: bool,
    /// Changes whenever an external start/stop request can supersede a
    /// temporary state transition used by the xchar fallback.
    transition_seq: usize,
}

#[derive(Debug)]
pub struct TtyCoreData {
    tty_driver: Arc<TtyDriver>,
    termios: RwLock<Termios>,
    /// Serializes termios users with the update + driver/ldisc notification transaction.
    termios_rwsem: RwSem<()>,
    name: String,
    flags: RwLock<TtyFlag>,
    /// 在初始化时即确定不会更改，所以这里不用加锁
    index: usize,
    vc_index: AtomicUsize,
    count: AtomicUsize,
    /// 窗口大小
    window_size: RwLock<WindowSize>,
    /// 读等待队列
    read_wq: EventWaitQueue,
    /// 写等待队列
    write_wq: EventWaitQueue,
    /// 串行化整个 tty write 调用，等价于 Linux tty->atomic_write_lock。
    write_lock: TtySleepLock,
    /// Serializes non-PTY first-open/last-close driver lifecycle callbacks.
    open_close_lock: TtySleepLock,
    /// User file descriptions; unlike `count`, this excludes the driver's
    /// persistent table reference.
    open_files: AtomicUsize,
    /// Serializes controlling-session changes with hangup.
    job_control_lock: TtySleepLock,
    /// 端口
    port: RwLock<Option<Arc<dyn TtyPort>>>,
    /// 前台进程
    ctrl: SpinLock<TtyControlInfo>,
    /// 是否正在关闭
    closing: AtomicBool,
    /// Incremented when a hangup starts so file instances opened before that
    /// point retain Linux's hung_up_tty_fops semantics independently of later
    /// reopens.
    hangup_generation: AtomicUsize,
    /// 流控状态
    flow: SpinLock<TtyFlowState>,
    /// 链接tty
    link: RwLock<Weak<TtyCore>>,
    /// epitems
    epitems: EPollItemList,
    /// Open file descriptions registered for asynchronous TTY notification.
    fasync_items: FAsyncItems,
    /// 设备号
    device_number: DeviceNumber,

    privete_fields: SpinLock<Option<Arc<dyn TtyCorePrivateField>>>,
}

impl TtyCoreData {
    #[inline]
    pub fn driver(&self) -> &Arc<TtyDriver> {
        &self.tty_driver
    }

    #[inline]
    pub fn flow_irqsave(&self) -> SpinLockGuard<'_, TtyFlowState> {
        self.flow.lock_irqsave()
    }

    #[inline]
    pub fn port(&self) -> Option<Arc<dyn TtyPort>> {
        self.port.read().clone()
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.index
    }

    #[inline]
    pub fn name(&self) -> &String {
        &self.name
    }

    pub fn device_number(&self) -> &DeviceNumber {
        &self.device_number
    }

    #[inline]
    pub fn flags(&self) -> TtyFlag {
        *self.flags.read_irqsave()
    }

    #[inline]
    pub fn flags_write(&self) -> RwLockWriteGuard<'_, TtyFlag> {
        self.flags.write_irqsave()
    }

    #[inline]
    pub fn hangup_generation(&self) -> usize {
        self.hangup_generation.load(Ordering::Acquire)
    }

    #[inline]
    pub fn file_hung_up(&self, file_hangup_generation: usize) -> bool {
        self.hangup_generation() != file_hangup_generation
    }

    /// Snapshot the generation assigned to a newly opening file.
    ///
    /// A file which races with an in-progress hangup belongs to the generation
    /// being hung up. Holding the flags read lock pairs this decision with the
    /// generation increment performed under the flags write lock.
    pub fn file_open_hangup_generation(&self) -> usize {
        let flags = self.flags.read_irqsave();
        let generation = self.hangup_generation.load(Ordering::Acquire);
        if flags.contains(TtyFlag::HUPPING) {
            generation.wrapping_sub(1)
        } else {
            generation
        }
    }

    /// Clear a completed pre-open hangup only if no newer hangup raced with
    /// this open. The generation comparison and flag update share the same
    /// critical section as tty_vhangup's generation increment.
    pub fn finish_file_open(&self, file_hangup_generation: usize) {
        let mut flags = self.flags.write_irqsave();
        if self.hangup_generation.load(Ordering::Acquire) == file_hangup_generation {
            flags.remove(TtyFlag::HUPPED);
        }
    }

    pub fn add_fasync(
        &self,
        file_hangup_generation: usize,
        item: FAsyncItem,
    ) -> Result<(), SystemError> {
        let flags = self.flags.read_irqsave();
        if flags.contains(TtyFlag::HUPPING)
            || self.hangup_generation.load(Ordering::Acquire) != file_hangup_generation
        {
            return Err(SystemError::ENOTTY);
        }
        self.fasync_items.add(item);
        Ok(())
    }

    pub fn remove_fasync(&self, file: &Weak<crate::filesystem::vfs::file::File>) {
        self.fasync_items.remove(file);
    }

    pub fn remove_fasync_file(&self, file: &crate::filesystem::vfs::file::File) {
        self.fasync_items.remove_file(file);
    }

    pub fn private_fields(&self) -> Option<Arc<dyn TtyCorePrivateField>> {
        self.privete_fields.lock().clone()
    }

    #[inline]
    pub fn termios(&self) -> RwLockReadGuard<'_, Termios> {
        self.termios.read_irqsave()
    }

    #[inline]
    pub fn termios_write(&self) -> RwLockWriteGuard<'_, Termios> {
        self.termios.write_irqsave()
    }

    /// Snapshot only a fully committed termios transaction.
    pub fn committed_termios_snapshot(&self) -> Termios {
        let _guard = self.termios_read_lock();
        *self.termios()
    }

    #[inline]
    pub fn termios_read_lock(&self) -> RwSemReadGuard<'_, ()> {
        self.termios_rwsem.read()
    }

    #[inline]
    pub fn termios_read_lock_interruptible(&self) -> Result<RwSemReadGuard<'_, ()>, SystemError> {
        self.termios_rwsem.read_interruptible()
    }

    #[inline]
    pub fn termios_try_read_lock(&self) -> Option<RwSemReadGuard<'_, ()>> {
        self.termios_rwsem.try_read()
    }

    #[inline]
    pub fn termios_write_lock_interruptible(&self) -> Result<RwSemWriteGuard<'_, ()>, SystemError> {
        self.termios_rwsem.write_interruptible()
    }

    #[inline]
    pub fn termios_write_lock(&self) -> RwSemWriteGuard<'_, ()> {
        self.termios_rwsem.write()
    }

    #[inline]
    pub fn set_termios(&self, termios: Termios) {
        let mut termios_guard = self.termios_write();
        *termios_guard = termios;
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.count.load(Ordering::SeqCst)
    }

    pub fn count_valid(&self) -> bool {
        let cnt = self.count();
        // 暂时认为有效的count范围是(0, usize::MAX / 2)
        cnt > 0 && cnt < usize::MAX / 2
    }

    #[inline]
    pub fn add_count(&self) {
        self.count
            .fetch_add(1, core::sync::atomic::Ordering::SeqCst);
    }

    pub fn dec_count(&self) -> usize {
        self.count
            .fetch_sub(1, core::sync::atomic::Ordering::SeqCst)
    }

    #[inline]
    pub fn read_wq(&self) -> &EventWaitQueue {
        &self.read_wq
    }

    #[inline]
    pub fn write_wq(&self) -> &EventWaitQueue {
        &self.write_wq
    }

    pub fn write_lock(&self) -> &TtySleepLock {
        &self.write_lock
    }

    pub(crate) fn open_close_lock(&self) -> &TtySleepLock {
        &self.open_close_lock
    }

    /// Caller must hold `open_close_lock`.
    pub(crate) fn begin_file_open(&self) -> bool {
        self.open_files.fetch_add(1, Ordering::SeqCst) == 0
    }

    /// Caller must hold `open_close_lock`.
    pub(crate) fn end_file_open(&self) -> bool {
        let count = self.open_files.load(Ordering::SeqCst);
        if count == 0 {
            return false;
        }
        self.open_files.store(count - 1, Ordering::SeqCst);
        count == 1
    }

    #[inline]
    pub fn job_control_lock(&self) -> &TtySleepLock {
        &self.job_control_lock
    }

    #[inline]
    pub fn contorl_info_irqsave(&self) -> SpinLockGuard<'_, TtyControlInfo> {
        self.ctrl.lock_irqsave()
    }

    #[inline]
    pub fn window_size_upgradeable(&self) -> RwLockUpgradableGuard<'_, WindowSize> {
        self.window_size.upgradeable_read()
    }

    #[inline]
    pub fn window_size(&self) -> RwLockReadGuard<'_, WindowSize> {
        self.window_size.read()
    }

    #[inline]
    pub fn window_size_write(&self) -> RwLockWriteGuard<'_, WindowSize> {
        self.window_size.write()
    }

    #[inline]
    pub fn is_closing(&self) -> bool {
        self.closing.load(core::sync::atomic::Ordering::SeqCst)
    }

    #[inline]
    pub fn vc_data(&self) -> Option<Arc<SpinLock<VirtualConsoleData>>> {
        vc_manager().get(self.vc_index()?).unwrap().vc_data()
    }

    pub fn set_vc_index(&self, index: usize) {
        self.vc_index.store(index, Ordering::SeqCst);
    }

    pub fn vc_index(&self) -> Option<usize> {
        let x = self.vc_index.load(Ordering::SeqCst);
        if x == usize::MAX {
            return None;
        }
        return Some(x);
    }

    #[inline]
    pub fn link(&self) -> Option<Arc<TtyCore>> {
        self.link.read().upgrade()
    }

    pub fn checked_link(&self) -> Result<Arc<TtyCore>, SystemError> {
        if let Some(link) = self.link() {
            return Ok(link);
        }
        return Err(SystemError::ENODEV);
    }

    pub fn set_link(&self, link: Weak<TtyCore>) {
        *self.link.write() = link;
    }

    pub fn init_termios(&self) {
        let tty_index = self.index();
        let driver = self.driver();
        // 初始化termios
        if !driver
            .flags()
            .contains(super::tty_driver::TtyDriverFlag::TTY_DRIVER_RESET_TERMIOS)
        {
            // 先查看是否有已经保存的termios
            if let Some(t) = driver.saved_termios().get(tty_index) {
                let mut termios = *t;
                termios.line = driver.init_termios().line;
                self.set_termios(termios);
            }
        }
        // TODO:设置termios波特率？
    }

    #[inline]
    pub fn add_epitem(&self, epitem: Arc<EPollItem>) {
        self.epitems.add(epitem)
    }

    pub fn remove_epitem(&self, epitem: &Arc<EPollItem>) -> Result<(), SystemError> {
        self.epitems.remove(epitem)
    }

    pub fn epitems(&self) -> &EPollItemList {
        &self.epitems
    }

    pub fn do_write(&self, buf: &[u8], mut nr: usize) -> Result<usize, SystemError> {
        // 关闭中断
        if let Some(vc_data) = self.vc_data() {
            let mut vc_data_guard = vc_data.lock_irqsave();
            let mut offset = 0;

            // 这个参数是用来扫描unicode字符的，但是这部分目前未完成，先写着
            let mut rescan = false;
            let mut ch: u32 = 0;

            let mut draw = DrawRegion::default();

            // 首先隐藏光标再写
            vc_data_guard.hide_cursor();

            while nr != 0 {
                if !rescan {
                    // Match Linux's `while (!stopped)` plus
                    // `goto rescan_last_byte`: stop before consuming a new
                    // byte, but always finish a byte already marked rescan.
                    if self.flow.lock_irqsave().stopped {
                        break;
                    }
                    ch = buf[offset] as u32;
                    offset += 1;
                    nr -= 1;
                }

                let (tc, rescan_last) = vc_data_guard.translate(&mut ch);
                if tc.is_none() {
                    // 表示未转换完成
                    continue;
                }

                let tc = tc.unwrap();
                rescan = rescan_last;

                if vc_data_guard.is_control(tc, ch) {
                    vc_data_guard.flush(&mut draw);
                    vc_data_guard.do_control(ch);
                    continue;
                }

                if !vc_data_guard.console_write_normal(tc, ch, &mut draw) {
                    continue;
                }
            }

            vc_data_guard.flush(&mut draw);

            // TODO: notify update
            return Ok(offset);
        } else {
            return Ok(0);
        }
    }
}

impl TtyOperation for TtyCore {
    #[inline]
    fn open(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().open(tty);
    }

    #[inline]
    fn write_room(&self, tty: &TtyCoreData) -> usize {
        return self.core().tty_driver.driver_funcs().write_room(tty);
    }

    #[inline]
    fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
        return self.core().tty_driver.driver_funcs().write(tty, buf, nr);
    }

    #[inline]
    fn flush_chars(&self, tty: &TtyCoreData) {
        self.core().tty_driver.driver_funcs().flush_chars(tty);
    }

    #[inline]
    fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().put_char(tty, ch);
    }

    #[inline]
    fn send_xchar(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
        self.core().tty_driver.driver_funcs().send_xchar(tty, ch)
    }

    #[inline]
    fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().install(driver, tty);
    }

    #[inline]
    fn start(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().start(tty);
    }

    #[inline]
    fn stop(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().stop(tty);
    }

    #[inline]
    fn ioctl(&self, tty: Arc<TtyCore>, cmd: u32, arg: usize) -> Result<(), SystemError> {
        return self.core().tty_driver.driver_funcs().ioctl(tty, cmd, arg);
    }

    #[inline]
    fn chars_in_buffer(&self, tty: &TtyCoreData) -> usize {
        return tty.tty_driver.driver_funcs().chars_in_buffer(tty);
    }

    #[inline]
    fn wait_until_sent(&self, tty: &TtyCoreData) -> Result<(), SystemError> {
        tty.tty_driver.driver_funcs().wait_until_sent(tty)
    }

    #[inline]
    fn set_termios(&self, tty: Arc<TtyCore>, old_termios: Termios) -> Result<(), SystemError> {
        return self
            .core()
            .tty_driver
            .driver_funcs()
            .set_termios(tty, old_termios);
    }

    fn close(&self, tty: Arc<TtyCore>) -> Result<(), SystemError> {
        let non_pty = tty.core().driver().tty_driver_type() != TtyDriverType::Pty;
        let _open_close_guard = non_pty.then(|| tty.core().open_close_lock().lock());
        let is_non_pty_last = non_pty && tty.core().end_file_open();
        self.core().dec_count();
        let cnt = self.core().count();
        // TODO: fix pty slave close issue
        let subtype = tty.core().driver().tty_driver_sub_type();
        let is_pty_slave_last = cnt == 1 && subtype == TtyDriverSubType::PtySlave;
        let is_pty_master_last = cnt == 1 && subtype == TtyDriverSubType::PtyMaster;
        let final_release = !self.core().count_valid();
        if final_release || is_pty_slave_last || is_pty_master_last || is_non_pty_last {
            // log::debug!(
            //     "TtyCore close: ref count: {}, tty: {}",
            //     cnt,
            //     tty.core().name()
            // );
            let r = self.core().tty_driver.driver_funcs().close(tty.clone());
            // Linux pty_close() runs when the last user fd closes even though
            // the peer keeps the tty structure count at one. The controlling
            // session remains attached in that case and may reopen /dev/tty;
            // only a true final structure release clears it here.
            if final_release || is_non_pty_last {
                self.reset_flow_state();
            }
            if final_release {
                let _ = TtyJobCtrlManager::remove_session_tty(&tty);
            }
            return r;
        }
        Ok(())
    }

    fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
        self.core.tty_driver.driver_funcs().resize(tty, winsize)
    }
}

bitflags! {
    pub struct TtyFlag: u32 {
        /// 终端被节流
        const THROTTLED		= 1 << 0;
        /// 终端输入输出错误状态
        const IO_ERROR		= 1 << 1;
        /// 终端的其他一方已关闭
        const OTHER_CLOSED	= 1 << 2;
        /// 终端处于独占状态
        const EXCLUSIVE		= 1 << 3;
        /// 终端执行写唤醒操作
        const DO_WRITE_WAKEUP	= 1 << 5;
        /// 终端线路驱动程序已打开
        const LDISC_OPEN		= 1 << 11;
        /// 终端伪终端设备已锁定
        const PTY_LOCK		= 1 << 16;
        /// 终端禁用写分裂操作
        const NO_WRITE_SPLIT	= 1 << 17;
        /// 终端挂断（挂起）状态
        const HUPPED		= 1 << 18;
        /// 终端正在挂断（挂起）
        const HUPPING		= 1 << 19;
        /// 终端线路驱动程序正在更改
        const LDISC_CHANGING	= 1 << 20;
        /// 终端线路驱动程序已停止
        const LDISC_HALTED	= 1 << 22;
    }

    #[derive(Default)]
    pub struct TtyPacketStatus: u8 {
        /* Used for packet mode */
        const TIOCPKT_DATA		=  0;
        const TIOCPKT_FLUSHREAD	=  1;
        const TIOCPKT_FLUSHWRITE	=  2;
        const TIOCPKT_STOP		=  4;
        const TIOCPKT_START		=  8;
        const TIOCPKT_NOSTOP		= 16;
        const TIOCPKT_DOSTOP		= 32;
        const TIOCPKT_IOCTL		= 64;
    }
}

#[derive(Debug, PartialEq)]
pub enum EchoOperation {
    /// 开始特殊操作。
    Start,
    /// 向后移动光标列。
    MoveBackCol,
    /// 设置规范模式下的列位置。
    SetCanonCol,
    /// 擦除制表符。
    EraseTab,

    Undefined(u8),
}

impl EchoOperation {
    pub fn from_u8(num: u8) -> EchoOperation {
        match num {
            0xff => Self::Start,
            0x80 => Self::MoveBackCol,
            0x81 => Self::SetCanonCol,
            0x82 => Self::EraseTab,
            _ => Self::Undefined(num),
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            EchoOperation::Start => 0xff,
            EchoOperation::MoveBackCol => 0x80,
            EchoOperation::SetCanonCol => 0x81,
            EchoOperation::EraseTab => 0x82,
            EchoOperation::Undefined(num) => num,
        }
    }
}

pub struct TtyIoctlCmd;

#[allow(dead_code)]
impl TtyIoctlCmd {
    /// 获取终端参数
    pub const TCGETS: u32 = 0x5401;
    /// 设置终端参数
    pub const TCSETS: u32 = 0x5402;
    /// 设置终端参数并等待所有输出完成
    pub const TCSETSW: u32 = 0x5403;
    /// 设置终端参数并且等待所有输出完成，但在这之前将终端清空
    pub const TCSETSF: u32 = 0x5404;
    /// 获取终端参数
    pub const TCGETA: u32 = 0x5405;
    /// 设置终端参数
    pub const TCSETA: u32 = 0x5406;
    /// 设置终端参数并等待所有输出完成
    pub const TCSETAW: u32 = 0x5407;
    /// 设置终端参数并且等待所有输出完成，但在这之前将终端清空
    pub const TCSETAF: u32 = 0x5408;
    /// 发送零字节，等待所有输出完成
    pub const TCSBRK: u32 = 0x5409;
    /// 控制终端的流控
    pub const TCXONC: u32 = 0x540A;
    /// 刷新输入/输出缓冲区或者丢弃输入缓冲区
    pub const TCFLSH: u32 = 0x540B;
    /// 设置设备为独占模式
    pub const TIOCEXCL: u32 = 0x540C;
    /// 设置设备为非独占模式
    pub const TIOCNXCL: u32 = 0x540D;
    /// 设置当前进程的控制终端
    pub const TIOCSCTTY: u32 = 0x540E;
    /// 获取前台进程组
    pub const TIOCGPGRP: u32 = 0x540F;
    ///设置前台进程组
    pub const TIOCSPGRP: u32 = 0x5410;
    /// 获取输出队列的字节数
    pub const TIOCOUTQ: u32 = 0x5411;
    /// 模拟从终端输入字符
    pub const TIOCSTI: u32 = 0x5412;
    /// 获取窗口大小
    pub const TIOCGWINSZ: u32 = 0x5413;
    /// 设置窗口大小
    pub const TIOCSWINSZ: u32 = 0x5414;
    /// 获取终端控制信号的状态
    pub const TIOCMGET: u32 = 0x5415;
    /// 设置终端控制信号的位
    pub const TIOCMBIS: u32 = 0x5416;
    /// 清除终端控制信号的位
    pub const TIOCMBIC: u32 = 0x5417;
    /// 设置终端控制信号的状态
    pub const TIOCMSET: u32 = 0x5418;
    /// 获取软件载波状态
    pub const TIOCGSOFTCAR: u32 = 0x5419;
    /// 设置软件载波状态
    pub const TIOCSSOFTCAR: u32 = 0x541A;
    /// 获取输入队列的字节数
    pub const FIONREAD: u32 = 0x541B;
    /// Linux 特有命令
    pub const TIOCLINUX: u32 = 0x541C;
    /// 获取控制台设备
    pub const TIOCCONS: u32 = 0x541D;
    /// 获取串行设备参数
    pub const TIOCGSERIAL: u32 = 0x541E;
    /// 设置串行设备参数
    pub const TIOCSSERIAL: u32 = 0x541F;
    /// 设置套接字的报文模式
    pub const TIOCPKT: u32 = 0x5420;
    /// 设置非阻塞 I/O
    pub const FIONBIO: u32 = 0x5421;
    /// 清除控制终端
    pub const TIOCNOTTY: u32 = 0x5422;
    /// 设置终端线路驱动器
    pub const TIOCSETD: u32 = 0x5423;
    /// 获取终端线路驱动器
    pub const TIOCGETD: u32 = 0x5424;
    /// 发送终止条件
    pub const TCSBRKP: u32 = 0x5425;
    /// 开始发送零比特
    pub const TIOCSBRK: u32 = 0x5427;
    /// 停止发送零比特
    pub const TIOCCBRK: u32 = 0x5428;
    /// Return the session ID of FD
    pub const TIOCGSID: u32 = 0x5429;
    /// 设置ptl锁标记
    pub const TIOCSPTLCK: u32 = 0x40045431;
    /// 获取ptl锁标记
    pub const TIOCGPTLCK: u32 = 0x80045439;
    /// 获取packet标记
    pub const TIOCGPKT: u32 = 0x80045438;
    /// 获取pts index
    pub const TIOCGPTN: u32 = 0x80045430;
    /// Open the slave side of a Unix98 PTY from the master fd.
    pub const TIOCGPTPEER: u32 = 0x5441;
}

pub struct TtyFlushArg;

#[allow(dead_code)]
impl TtyFlushArg {
    /// 丢弃已收到但尚未读取的数据
    pub const TCIFLUSH: usize = 0;
    /// 丢弃已写入但尚未发送的数据
    pub const TCOFLUSH: usize = 1;
    /// 丢弃所有待处理输入和输出数据
    pub const TCIOFLUSH: usize = 2;
}

pub struct TtyFlowArg;

#[allow(dead_code)]
impl TtyFlowArg {
    pub const TCOOFF: usize = 0;
    pub const TCOON: usize = 1;
    pub const TCIOFF: usize = 2;
    pub const TCION: usize = 3;
}
