// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use fuchsia_sync::RwLock;
use futures::channel::mpsc::UnboundedSender;
use std::sync::Arc;

/// Class for storing a list of senders and certain operations on them.
/// add_sender_channel adds a sender to the list.
/// send_value sends the new_value to the receivers.
/// If there is a new channel, the sender will be added to the list in the class.
/// Whenever value is changed, every sender in the list should send the new value to the sender.
/// If the channel is closed, remove corresponding sender from the list.
pub struct SenderChannel<T> {
    pub sender_channel_vec: Arc<RwLock<Vec<UnboundedSender<T>>>>,
}

impl<T> SenderChannel<T>
where
    T: Copy,
{
    pub fn new() -> SenderChannel<T> {
        SenderChannel { sender_channel_vec: Arc::new(RwLock::new(Vec::new())) }
    }

    pub async fn add_sender_channel(&mut self, sender: UnboundedSender<T>) {
        self.sender_channel_vec.write().push(sender);
    }

    pub fn send_value(&mut self, new_value: T) {
        let mut sender_channel_vec = self.sender_channel_vec.write();
        sender_channel_vec.retain(|sender| {
            let sender_success = sender.unbounded_send(new_value);
            match sender_success {
                Ok(_v) => true,
                Err(_e) => false,
            }
        })
    }
}

#[cfg(test)]

mod tests {
    use super::*;

    use fuchsia_async as fasync;

    fn mock_sender_channel() -> SenderChannel<f64> {
        SenderChannel::new()
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_add_sender_channel() {
        let (channel_sender1, _channel_receiver1) = futures::channel::mpsc::unbounded::<f64>();
        let (channel_sender2, _channel_receiver2) = futures::channel::mpsc::unbounded::<f64>();
        let mut mock_sender_channel = mock_sender_channel();
        mock_sender_channel.add_sender_channel(channel_sender1).await;
        assert_eq!(mock_sender_channel.sender_channel_vec.write().len(), 1);
        mock_sender_channel.add_sender_channel(channel_sender2).await;
        assert_eq!(mock_sender_channel.sender_channel_vec.write().len(), 2);
    }
}
