use std::{
    path::Component,
    sync::{
        Arc,
        mpsc::{Receiver, Sender},
    },
};

use crate::{MemoryBank, SharedState, backend::memory::PhysAddr};

pub struct Serial {
    pub receiver: Receiver<u8>,
    pub buffer: Vec<u8>,

    pub visible: bool,
}

impl Serial {
    fn uart_io_thread(mem: MemoryBank, uart_base: PhysAddr, tx: Sender<u8>) {
        loop {
            let word = mem.read_word(uart_base);
            // println!("word {:#010X}", word);
            if word >> 24 == 0x01 {
                let byte = ((word >> 16) & 0xFF) as u8;
                let _ = tx.send(byte);
                mem.write_word(uart_base, 0x00_00_00_00); // clear valid flag
            }
            std::hint::spin_loop();
        }
    }

    pub fn new(uart_base: PhysAddr, state: Arc<SharedState>, mem_handle: MemoryBank) -> Self {
        let (sender, receiver) = std::sync::mpsc::channel();
        let _ = std::thread::spawn(move || Self::uart_io_thread(mem_handle, uart_base, sender));

        Self {
            visible: false,
            receiver,
            buffer: Vec::new(),
        }
    }

    pub fn update(&mut self) {
        while let Ok(byte) = self.receiver.try_recv() {
            self.buffer.push(byte);
        }
    }
}
