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

pub struct InspectableMessageConsumer {
    listen_to: Vec<MessageType>,
    system_channel_sender: Sender<Message>,
    input_channel_sender: Sender<Message>,
    input_channel_receiver: Receiver<Message>,
    received: Arc<RwLock<Vec<Message>>>
}

impl InspectableMessageConsumer {
    pub fn new(system_channel_sender: Sender<Message>, listen_to: Vec<MessageType>, received: Arc<RwLock<Vec<Message>>>) -> Self {
        let (sender, receiver) = channel::<Message>();

        Self {
            listen_to: listen_to,
            system_channel_sender: system_channel_sender,
            input_channel_sender: sender,
            input_channel_receiver: receiver,
            received: received
        }
    }

    pub fn inspect(&self) -> RwLockReadGuard<'_, Vec<Message>> {
        self.received.read().unwrap()
    }
}

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

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

    fn listen_to(&self) -> Vec<MessageType> {
        self.listen_to.clone()
    }

    fn run(&mut self) {
        loop {
            let message = self.input_channel_receiver.recv().unwrap();

            if message == Message::Halt {
                break;
            } else {
                println!("Component InspectableMessageConsumer received a message {:?}", message);
                self.received.write().unwrap().push(message);
            }
        }
    }
}
