use core::fmt::Debug;

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

use crate::{
    arch::ipc::signal::Signal,
    driver::{
        base::{
            char::CharDevice,
            class::Class,
            device::{
                bus::Bus,
                device_number::{DeviceNumber, Major},
                device_register,
                driver::Driver,
                Device, DeviceKObjType, DeviceType, IdTable,
            },
            kobject::{KObject, LockedKObjectState},
            kset::KSet,
        },
        serial::serial_init,
    },
    filesystem::{
        devfs::{devfs_register, DevFS, DeviceINode, LockedDevFSInode},
        devpts::{DevPtsFs, LockedDevPtsFSInode},
        epoll::{EPollEventType, EPollItem},
        kernfs::KernFSInode,
        vfs::{
            fasync::FAsyncItem,
            file::{File, FileFlags},
            utils::DName,
            FilePrivateData, FileType, IndexNode, InodeMode, Metadata, PollableInode,
        },
    },
    init::initcall::INITCALL_DEVICE,
    libs::{mutex::MutexGuard, rwlock::RwLock},
    mm::VirtAddr,
    process::ProcessManager,
    syscall::user_access::{UserBufferReader, UserBufferWriter},
    time::PosixTimeSpec,
};

use super::{
    kthread::tty_flush_thread_init,
    pty::unix98pty::{ptm_peer_inode, ptmx_open, pty_file_close},
    sysfs::sys_class_tty_instance,
    termios::WindowSize,
    tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
    tty_driver::{TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
    tty_job_control::TtyJobCtrlManager,
    tty_ldisc::TtyLdiscFileContext,
    virtual_terminal::vty_init,
};

#[derive(Debug)]
pub struct InnerTtyDevice {
    /// 当前设备所述的kset
    kset: Option<Arc<KSet>>,
    parent_kobj: Option<Weak<dyn KObject>>,
    /// 当前设备所述的总线
    bus: Option<Weak<dyn Bus>>,
    inode: Option<Arc<KernFSInode>>,
    driver: Option<Weak<dyn Driver>>,
    can_match: bool,

    metadata: Metadata,
}

impl InnerTtyDevice {
    pub fn new() -> Self {
        Self {
            kset: None,
            parent_kobj: None,
            bus: None,
            inode: None,
            driver: None,
            can_match: false,
            metadata: {
                let mut md =
                    Metadata::new(FileType::CharDevice, InodeMode::from_bits_truncate(0o755));
                // 对于字符设备，选择与 Linux devpts/devfs 一致的首选 I/O 块大小。
                // 1024 满足测试期望 (允许 1024 或 4096)。
                md.blk_size = 1024;
                md
            },
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum TtyType {
    Tty,
    Pty(PtyType),
}

#[derive(Debug, PartialEq)]
pub enum PtyType {
    Ptm,
    Pts,
}

#[cast_to([sync] Device, DeviceINode)]
pub struct TtyDevice {
    name: String,
    id_table: IdTable,
    tty_type: TtyType,
    inner: RwLock<InnerTtyDevice>,
    kobj_state: LockedKObjectState,
    /// TTY所属的文件系统
    fs: RwLock<TtyDeviceFs>,
    parent: RwLock<TtyDeviceParent>,
}

pub enum TtyDeviceFs {
    DevFs(Weak<DevFS>),
    DevPtsFs(Weak<DevPtsFs>),
    None,
}
pub enum TtyDeviceParent {
    DevFS(Weak<LockedDevFSInode>),
    DevPts(Weak<LockedDevPtsFSInode>),
    None,
}

impl TtyDevice {
    pub fn new(name: String, id_table: IdTable, tty_type: TtyType) -> Arc<TtyDevice> {
        let dev_num = id_table.device_number();
        let dev = TtyDevice {
            name,
            id_table,
            inner: RwLock::new(InnerTtyDevice::new()),
            kobj_state: LockedKObjectState::new(None),
            fs: RwLock::new(TtyDeviceFs::None),
            parent: RwLock::new(TtyDeviceParent::None),
            tty_type,
        };

        dev.inner.write().metadata.raw_dev = dev_num;

        Arc::new(dev)
    }

    pub fn inner_write(&self) -> crate::libs::rwlock::RwLockWriteGuard<'_, InnerTtyDevice> {
        self.inner.write()
    }

    pub fn name_ref(&self) -> &str {
        &self.name
    }

    fn tty_file(private_data: &FilePrivateData) -> Result<&TtyFilePrivateData, SystemError> {
        if let FilePrivateData::Tty(tty_priv) = private_data {
            Ok(tty_priv)
        } else {
            Err(SystemError::EIO)
        }
    }

    /// tty_open_current_tty - get locked tty of current task
    #[inline(never)]
    fn open_current_tty(
        &self,
        dev_num: DeviceNumber,
        data: &mut FilePrivateData,
    ) -> Option<Arc<TtyCore>> {
        // log::debug!("open_current_tty: dev_num: {}", dev_num);
        if dev_num != DeviceNumber::new(Major::TTYAUX_MAJOR, 0) {
            // log::debug!("Not a tty device, dev_num: {}", dev_num);
            return None;
        }

        let current_tty = TtyJobCtrlManager::get_current_tty()?;

        if let FilePrivateData::Tty(tty_priv) = data {
            tty_priv.flags.insert(FileFlags::O_NONBLOCK);
        }

        current_tty.reopen().ok()?;
        Some(current_tty)
    }
}

impl Debug for TtyDevice {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("TtyDevice")
            .field("name", &self.name)
            .finish()
    }
}

impl PollableInode for TtyDevice {
    fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
        let tty_file = TtyDevice::tty_file(private_data)?;
        if tty_file.is_hung_up() {
            return Ok((EPollEventType::EPOLLIN
                | EPollEventType::EPOLLOUT
                | EPollEventType::EPOLLERR
                | EPollEventType::EPOLLHUP
                | EPollEventType::EPOLLRDNORM
                | EPollEventType::EPOLLWRNORM)
                .bits() as usize);
        }

        let tty = tty_file.tty();
        tty.ldisc().poll(tty)
    }

    fn add_epitem(
        &self,
        epitem: Arc<EPollItem>,
        private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        let tty_file = TtyDevice::tty_file(private_data)?;
        if tty_file.is_hung_up() {
            // hung_up_tty_poll() is permanently ready and does not register
            // a wait queue. epoll observes the fixed mask immediately after
            // this callback.
            return Ok(());
        }

        let tty = tty_file.tty();
        let core = tty.core();
        core.add_epitem(epitem);
        Ok(())
    }

    fn remove_epitem(
        &self,
        epitem: &Arc<EPollItem>,
        private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        let tty_file = TtyDevice::tty_file(private_data)?;
        let hung_up = tty_file.is_hung_up();
        let tty = tty_file.tty();
        let core = tty.core();
        match core.remove_epitem(epitem) {
            Err(SystemError::ENOENT) if hung_up => Ok(()),
            result => result,
        }
    }

    fn add_fasync(
        &self,
        fasync_item: FAsyncItem,
        private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        let tty_file = Self::tty_file(private_data)?;
        tty_file
            .tty()
            .core()
            .add_fasync(tty_file.hangup_generation, fasync_item)
    }

    fn remove_fasync(
        &self,
        file: &Weak<File>,
        private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        Self::tty_file(private_data)?
            .tty()
            .core()
            .remove_fasync(file);
        Ok(())
    }

    fn release_fasync(
        &self,
        file: &File,
        private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        Self::tty_file(private_data)?
            .tty()
            .core()
            .remove_fasync_file(file);
        Ok(())
    }
}

impl IndexNode for TtyDevice {
    fn open(
        &self,
        mut data: MutexGuard<FilePrivateData>,
        mode: &crate::filesystem::vfs::file::FileFlags,
    ) -> Result<(), SystemError> {
        if self.tty_type == TtyType::Pty(PtyType::Ptm) {
            return ptmx_open(self, data, mode);
        }
        let dev_num = self.metadata()?.raw_dev;
        // /dev/tty 仅在已有控制终端时才能打开；否则返回 ENXIO
        let mut tty = if dev_num == DeviceNumber::new(Major::TTYAUX_MAJOR, 0) {
            if let Some(current) = self.open_current_tty(dev_num, &mut data) {
                Some(current)
            } else {
                return Err(SystemError::ENXIO);
            }
        } else {
            None
        };

        // log::debug!(
        //     "TtyDevice::open: dev_num: {}, current pid: {}",
        //     dev_num,
        //     ProcessManager::current_pid()
        // );
        if tty.is_none() {
            tty = self.open_current_tty(dev_num, &mut data);
        }
        if tty.is_none() {
            let (index, driver) =
                TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;

            tty = Some(driver.open_tty(Some(index))?);
        }

        let tty = tty.unwrap();
        let hangup_generation = tty.core().file_open_hangup_generation();

        // 设置privdata
        *data = FilePrivateData::Tty(TtyFilePrivateData {
            tty: tty.clone(),
            flags: *mode,
            hangup_generation,
        });

        tty.core().contorl_info_irqsave().clear_dead_session();

        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 first_open = non_pty && tty.core().begin_file_open();
        if first_open {
            tty.reset_flow_state();
        }
        let ret = tty.open(tty.core());
        if let Err(err) = ret {
            if non_pty {
                tty.core().end_file_open();
            }
            tty.core().dec_count();
            *data = FilePrivateData::Unused;
            if err == SystemError::ENOSYS {
                return Err(SystemError::ENODEV);
            }
            return Err(err);
        }

        // A successful open after a completed hangup is a normal tty file in
        // Linux. Do not clear a hangup which raced with this open: its
        // generation change marks this file as one of the hung-up instances.
        tty.core().finish_file_open(hangup_generation);
        drop(open_close_guard);

        let driver = tty.core().driver();
        // 考虑 O_NOCTTY：显式指定则不设置控制终端；pty master 也不会成为控制终端。
        if !(mode.contains(FileFlags::O_NOCTTY)
            || mode.is_write_only()
            || (driver.tty_driver_type() == TtyDriverType::Pty
                && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster))
        {
            // The helper revalidates and commits the controlling-tty state as
            // one membership/tty/signal transaction.
            TtyJobCtrlManager::proc_set_tty(tty);
        }

        Ok(())
    }

    fn read_at(
        &self,
        _offset: usize,
        len: usize,
        buf: &mut [u8],
        data: MutexGuard<FilePrivateData>,
    ) -> Result<usize, system_error::SystemError> {
        let tty_file = Self::tty_file(&data)?;
        if tty_file.is_hung_up() {
            return Ok(0);
        }
        let tty = tty_file.tty();
        let file_context = TtyLdiscFileContext {
            flags: tty_file.flags,
            hangup_generation: tty_file.hangup_generation,
        };

        drop(data);

        let ld = tty.ldisc();
        let mut offset = 0;
        let mut cookie = false;

        // 边界检查：防止整数下溢
        if len > buf.len() {
            return Err(SystemError::EINVAL);
        }

        loop {
            let mut size = (len - offset).min(buf.len() - offset);
            size = ld.read(
                tty.clone(),
                &mut buf[offset..],
                size,
                &mut cookie,
                0,
                file_context,
            )?;
            // 本次迭代未读取到数据，可能是EOF或暂时无数据可读
            if size == 0 {
                break;
            }

            offset += size;

            // 已满足读取请求或缓冲区已满
            if offset >= len || offset >= buf.len() {
                break;
            }

            // 没有更多数据
            if !cookie {
                break;
            }
        }

        return Ok(offset);
    }

    fn write_at(
        &self,
        _offset: usize,
        len: usize,
        buf: &[u8],
        data: MutexGuard<FilePrivateData>,
    ) -> Result<usize, system_error::SystemError> {
        let mut count = len;
        let tty_file = Self::tty_file(&data)?;
        if tty_file.is_hung_up() {
            return Err(SystemError::EIO);
        }
        let tty = tty_file.tty();
        let file_context = TtyLdiscFileContext {
            flags: tty_file.flags,
            hangup_generation: tty_file.hangup_generation,
        };
        drop(data);
        let ld = tty.ldisc();
        let core = tty.core();
        let write_guard = core
            .write_lock()
            .lock_interruptible(file_context.flags.contains(FileFlags::O_NONBLOCK))?;
        let mut chunk = 2048;
        if core.flags().contains(TtyFlag::NO_WRITE_SPLIT) {
            chunk = 65536;
        }
        chunk = chunk.min(count);

        let pcb = ProcessManager::current_pcb();
        let mut written = 0;
        loop {
            // 至少需要写多少
            let size = chunk.min(count);

            // 将数据从buf拷贝到writebuf

            let ret = match ld.write(tty.clone(), &buf[written..], size, file_context) {
                Ok(ret) => ret,
                Err(err) => {
                    if written != 0 {
                        break;
                    }
                    drop(write_guard);
                    core.write_wq()
                        .wakeup_any(EPollEventType::EPOLLOUT.bits() as u64);
                    return Err(err);
                }
            };
            if ret == 0 {
                break;
            }

            written += ret;
            count -= ret;

            if count == 0 {
                break;
            }

            if pcb.has_pending_signal_fast() {
                if written != 0 {
                    break;
                }
                drop(write_guard);
                core.write_wq()
                    .wakeup_any(EPollEventType::EPOLLOUT.bits() as u64);
                return Err(SystemError::ERESTARTSYS);
            }
        }

        if written > 0 {
            // todo: 更新时间
        }

        drop(write_guard);
        core.write_wq()
            .wakeup_any(EPollEventType::EPOLLOUT.bits() as u64);
        Ok(written)
    }

    fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
        match &*self.fs.read() {
            TtyDeviceFs::DevFs(fs) => fs.upgrade().unwrap(),
            TtyDeviceFs::DevPtsFs(fs) => fs.upgrade().unwrap(),
            TtyDeviceFs::None => {
                panic!("TtyDevice has no filesystem set");
            }
        }
    }

    fn dname(&self) -> Result<DName, SystemError> {
        Ok(self.name.clone().into())
    }

    fn as_any_ref(&self) -> &dyn core::any::Any {
        self
    }

    fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
        todo!()
    }

    fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
        Ok(self.inner.read().metadata.clone())
    }

    fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
        let mut guard = self.inner_write();
        guard.metadata = metadata.clone();

        Ok(())
    }

    fn update_atime(&self, now: PosixTimeSpec, relatime: bool) -> Result<(), SystemError> {
        let mut guard = self.inner_write();
        crate::filesystem::vfs::update_atime_locked(&mut guard.metadata, now, relatime);
        Ok(())
    }

    fn page_cache(&self) -> Option<Arc<crate::filesystem::page_cache::PageCache>> {
        // TTY设备是字符设备，不需要页面缓存
        None
    }

    fn close(&self, data: MutexGuard<FilePrivateData>) -> Result<(), SystemError> {
        let (tty, _flags) = if let FilePrivateData::Tty(tty_priv) = &*data {
            (tty_priv.tty(), tty_priv.flags)
        } else {
            return Err(SystemError::EIO);
        };

        drop(data);
        let ret = tty.close(tty.clone());
        pty_file_close(&tty);
        ret
    }

    fn resize(&self, _len: usize) -> Result<(), SystemError> {
        Ok(())
    }

    fn ioctl(
        &self,
        cmd: u32,
        arg: usize,
        data: MutexGuard<FilePrivateData>,
    ) -> Result<usize, SystemError> {
        let tty_file = Self::tty_file(&data)?;
        let hung_up = tty_file.is_hung_up();
        let tty = tty_file.tty();

        // Drop the lock early: tty ioctl paths may block.
        drop(data);

        // Linux replaces only the file instances which existed at hangup
        // with hung_up_tty_fops. A later successful reopen must remain usable.
        // Check the original file endpoint before PTY master mode ioctls
        // redirect to the slave.
        if hung_up {
            return if cmd == TtyIoctlCmd::TIOCSPGRP {
                Err(SystemError::ENOTTY)
            } else {
                Err(SystemError::EIO)
            };
        }

        match cmd {
            TtyIoctlCmd::TIOCSETD
            | TtyIoctlCmd::TIOCSBRK
            | TtyIoctlCmd::TIOCCBRK
            | TtyIoctlCmd::TCSBRK
            | TtyIoctlCmd::TCSBRKP => {
                TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
                if cmd != TtyIoctlCmd::TIOCCBRK {
                    tty.wait_until_sent(tty.core())?;
                }
            }
            _ => {}
        }
        match cmd {
            TtyIoctlCmd::TIOCSBRK
            | TtyIoctlCmd::TIOCCBRK
            | TtyIoctlCmd::TCSBRK
            | TtyIoctlCmd::TCSBRKP => return Ok(0),
            TtyIoctlCmd::TIOCSETD => {
                let reader =
                    UserBufferReader::new(arg as *const i32, core::mem::size_of::<i32>(), true)?;
                let disc = reader.read_one_from_user::<i32>(0)?;
                if disc != 0 {
                    return Err(SystemError::ENODEV);
                }
                return Ok(0);
            }
            TtyIoctlCmd::TIOCGPTPEER => {
                let flags = FileFlags::from_bits(arg as u32).ok_or(SystemError::EINVAL)?;
                let cloexec = flags.contains(FileFlags::O_CLOEXEC);
                let slave_inode = ptm_peer_inode(tty)?;
                let fd_table = ProcessManager::current_pcb().fd_table();
                let reserved_fd = fd_table.write().reserve_fd(cloexec)?;
                let file = match File::new(slave_inode, flags) {
                    Ok(file) => file,
                    Err(err) => {
                        fd_table.write().release_reserved_fd(reserved_fd);
                        return Err(err);
                    }
                };
                return match fd_table.write().install_reserved_fd(reserved_fd, file) {
                    Ok(fd) => Ok(fd as usize),
                    Err(err) => {
                        fd_table.write().release_reserved_fd(reserved_fd);
                        Err(err)
                    }
                };
            }
            TtyIoctlCmd::TIOCGWINSZ => {
                let core = tty.core();
                let winsize = *core.window_size();

                let mut user_writer = UserBufferWriter::new(
                    VirtAddr::new(arg).as_ptr::<WindowSize>(),
                    core::mem::size_of::<WindowSize>(),
                    true,
                )?;

                let err = user_writer.copy_one_to_user(&winsize, 0);
                if err.is_err() {
                    return Err(SystemError::EFAULT);
                }
                return Ok(0);
            }
            TtyIoctlCmd::TIOCSWINSZ => {
                let reader = UserBufferReader::new(
                    arg as *const (),
                    core::mem::size_of::<WindowSize>(),
                    true,
                )?;

                let user_winsize = reader.read_one_from_user::<WindowSize>(0)?;

                let ret = tty.resize(tty.clone(), user_winsize);

                if ret != Err(SystemError::ENOSYS) {
                    return ret.map(|_| 0);
                } else {
                    return tty.tty_do_resize(user_winsize).map(|_| 0);
                }
            }
            _ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
                Ok(_) => {
                    return Ok(0);
                }
                Err(e) => {
                    if e != SystemError::ENOIOCTLCMD {
                        return Err(e);
                    }
                }
            },
        }

        match tty.ioctl(tty.clone(), cmd, arg) {
            Ok(_) => {
                return Ok(0);
            }
            Err(e) => {
                if e != SystemError::ENOIOCTLCMD {
                    return Err(e);
                }
            }
        }
        tty.ldisc().ioctl(tty, cmd, arg)?;

        Ok(0)
    }

    fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
        Ok(self)
    }

    fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
        let parent = self.parent.read();
        match &*parent {
            TtyDeviceParent::DevFS(devfs) => Ok(devfs.upgrade().unwrap()),
            TtyDeviceParent::DevPts(devpts) => Ok(devpts.upgrade().unwrap()),
            TtyDeviceParent::None => panic!("TtyDevice has no filesystem set"),
        }
    }
}

impl DeviceINode for TtyDevice {
    fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
        *self.fs.write() = TtyDeviceFs::DevFs(fs);
    }

    fn set_parent(&self, parent: Weak<crate::filesystem::devfs::LockedDevFSInode>) {
        *self.parent.write() = TtyDeviceParent::DevFS(parent);
    }

    fn set_devpts_fs(&self, devpts: Weak<crate::filesystem::devpts::DevPtsFs>) {
        *self.fs.write() = TtyDeviceFs::DevPtsFs(devpts);
    }

    fn set_devpts_parent(&self, parent: Weak<LockedDevPtsFSInode>) {
        *self.parent.write() = TtyDeviceParent::DevPts(parent);
    }
}

impl KObject for TtyDevice {
    fn as_any_ref(&self) -> &dyn core::any::Any {
        self
    }

    fn set_inode(&self, inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
        self.inner.write().inode = inode;
    }

    fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
        self.inner.read().inode.clone()
    }

    fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
        self.inner.read().parent_kobj.clone()
    }

    fn set_parent(&self, parent: Option<alloc::sync::Weak<dyn KObject>>) {
        self.inner.write().parent_kobj = parent
    }

    fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
        self.inner.read().kset.clone()
    }

    fn set_kset(&self, kset: Option<Arc<crate::driver::base::kset::KSet>>) {
        self.inner.write().kset = kset
    }

    fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
        Some(&DeviceKObjType)
    }

    fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {}

    fn name(&self) -> alloc::string::String {
        self.name.to_string()
    }

    fn set_name(&self, _name: alloc::string::String) {
        // self.name = name
    }

    fn kobj_state(
        &self,
    ) -> crate::libs::rwsem::RwSemReadGuard<'_, crate::driver::base::kobject::KObjectState> {
        self.kobj_state.read()
    }

    fn kobj_state_mut(
        &self,
    ) -> crate::libs::rwsem::RwSemWriteGuard<'_, crate::driver::base::kobject::KObjectState> {
        self.kobj_state.write()
    }

    fn set_kobj_state(&self, state: crate::driver::base::kobject::KObjectState) {
        *self.kobj_state.write() = state
    }
}

impl Device for TtyDevice {
    fn dev_type(&self) -> crate::driver::base::device::DeviceType {
        DeviceType::Char
    }

    fn id_table(&self) -> crate::driver::base::device::IdTable {
        self.id_table.clone()
    }

    fn bus(&self) -> Option<Weak<dyn Bus>> {
        self.inner.read().bus.clone()
    }

    fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
        self.inner.write().bus = bus
    }

    fn set_class(&self, _class: Option<Weak<dyn crate::driver::base::class::Class>>) {
        // do nothing
    }

    fn class(&self) -> Option<Arc<dyn Class>> {
        sys_class_tty_instance()
            .cloned()
            .map(|x| x as Arc<dyn Class>)
    }

    fn driver(&self) -> Option<Arc<dyn crate::driver::base::device::driver::Driver>> {
        self.inner.read().driver.clone()?.upgrade()
    }

    fn set_driver(
        &self,
        driver: Option<alloc::sync::Weak<dyn crate::driver::base::device::driver::Driver>>,
    ) {
        self.inner.write().driver = driver
    }

    fn is_dead(&self) -> bool {
        false
    }

    fn can_match(&self) -> bool {
        self.inner.read().can_match
    }

    fn set_can_match(&self, can_match: bool) {
        self.inner.write().can_match = can_match
    }

    fn state_synced(&self) -> bool {
        true
    }

    fn dev_parent(&self) -> Option<alloc::sync::Weak<dyn crate::driver::base::device::Device>> {
        None
    }

    fn set_dev_parent(
        &self,
        _dev_parent: Option<alloc::sync::Weak<dyn crate::driver::base::device::Device>>,
    ) {
        todo!()
    }
}

impl CharDevice for TtyDevice {
    fn read(&self, _len: usize, _buf: &mut [u8]) -> Result<usize, SystemError> {
        todo!()
    }

    fn write(&self, _len: usize, _buf: &[u8]) -> Result<usize, SystemError> {
        todo!()
    }

    fn sync(&self) -> Result<(), SystemError> {
        todo!()
    }
}

#[derive(Debug, Clone)]
pub struct TtyFilePrivateData {
    pub tty: Arc<TtyCore>,
    pub flags: FileFlags,
    pub hangup_generation: usize,
}

impl TtyFilePrivateData {
    pub fn tty(&self) -> Arc<TtyCore> {
        self.tty.clone()
    }

    pub fn is_hung_up(&self) -> bool {
        self.hangup_generation != self.tty.core().hangup_generation()
    }
}

/// 初始化tty设备和console子设备
#[unified_init(INITCALL_DEVICE)]
#[inline(never)]
pub fn tty_init() -> Result<(), SystemError> {
    let tty_device = TtyDevice::new(
        "tty".to_string(),
        IdTable::new(
            String::from("tty"),
            Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)),
        ),
        TtyType::Tty,
    );
    let console = TtyDevice::new(
        "console".to_string(),
        IdTable::new(
            String::from("console"),
            Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
        ),
        TtyType::Tty,
    );

    let devs = [tty_device, console];

    for dev in devs {
        // 将设备注册到devfs，TODO：这里console设备应该与tty在一个设备group里面
        device_register(dev.clone())?;
        devfs_register(&dev.name.clone(), dev)?;
    }

    serial_init()?;

    tty_flush_thread_init();
    return vty_init();
}
