use crate::message::*;
use crate::system::Component;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time;

pub struct ProgrammableMessageProducer {
    messages: Vec<Message>,
    system_channel_sender: Sender<Message>,
    input_channel_sender: Sender<Message>,
    input_channel_receiver: Receiver<Message>
}

impl ProgrammableMessageProducer {
    pub fn new(system_channel_sender: Sender<Message>, messages: Vec<Message>) -> Self {
        let (tx, rx) = channel();

        Self {
            messages,
            system_channel_sender,
            input_channel_sender: tx,
            input_channel_receiver: rx
        }
    }
}

impl Component for ProgrammableMessageProducer {
    fn get_name(&self) -> &str {
        "ProgrammableMessageProducer"
    }

    fn get_sender(&self) -> Sender<Message> {
        self.input_channel_sender.clone()
    }

    fn listen_to(&self) -> Vec<MessageType> {
        Vec::new()
    }

    fn run(&mut self) {
        let timeout = time::Duration::from_millis(1000/60);

        for message in self.messages.drain(..) {
            self.system_channel_sender.send(message).unwrap();

            match self.input_channel_receiver.recv_timeout(timeout) {
                Ok(Message::Halt) => return,
                _ => ()
            }
        }
    
        let _ = self.system_channel_sender.send(Message::Halt);
    }
}
