// Copyright 2018 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 std::mem;

use failure::Error;
use fuchsia_wayland_core as wl;

use crate::client::Client;
use crate::object::MessageReceiver;

/// Helper for constructing a |Registry|.
///
/// A proper registry implementation can support adding and removing |Global|s
/// at runtime. Since we do not yet support these features, we will only allow
/// |Global|s to be added at initialization time and then leave the |Registry|
/// immutable.
///
/// Note: the |Registry| only works for single-threaded event loops.
///
/// TODO(tjdetwiler): Allow interfaces to be added and removed from the
/// |Registry| dynamically.
pub struct RegistryBuilder {
    globals: Vec<Global>,
}

impl RegistryBuilder {
    pub fn new() -> Self {
        RegistryBuilder {
            globals: Vec::new(),
        }
    }

    /// Adds a new global interface to the registry.
    ///
    /// The wayland interface name & version are identified by the |Interface|
    /// provided. When a client attempts to bind to this global using
    /// |wl_registry::bind|, the closure will be called to create a
    /// |MessageReceiver| that will be use to handle requests to the instance
    /// of that global.
    pub fn add_global<
        I: wl::Interface + 'static,
        F: FnMut(wl::ObjectId, &mut Client) -> Result<Box<MessageReceiver>, Error> + Send + 'static,
    >(
        &mut self, _: I, bind: F,
    ) -> &mut Self {
        self.globals.push(Global {
            name: I::NAME,
            version: I::VERSION,
            requests: &I::REQUESTS,
            bind_fn: Box::new(bind),
        });
        self
    }

    pub fn build(&mut self) -> Registry {
        Registry {
            globals: mem::replace(&mut self.globals, vec![]),
        }
    }
}

/// The |Registry| holds the global interfaces that are advertised to clients.
pub struct Registry {
    globals: Vec<Global>,
}

impl Registry {
    pub fn globals(&mut self) -> &mut [Global] {
        self.globals.as_mut_slice()
    }
}

pub struct Global {
    name: &'static str,
    version: u32,
    requests: &'static wl::MessageGroupSpec,
    bind_fn: Box<FnMut(wl::ObjectId, &mut Client) -> Result<Box<MessageReceiver>, Error> + Send>,
}

impl Global {
    /// The wayland interface name for this global.
    pub fn interface(&self) -> &str {
        self.name
    }

    /// The wayland interface version for this global.
    pub fn version(&self) -> u32 {
        self.version
    }

    /// A descriptor of the set of requests this global can handle.
    pub fn request_spec(&self) -> &'static wl::MessageGroupSpec {
        self.requests
    }

    /// Create a new object instance for this global. The returned
    /// |MessageReceiver| will be used to handle all requests for the new
    /// object.
    pub fn bind(
        &mut self, id: wl::ObjectId, client: &mut Client,
    ) -> Result<Box<MessageReceiver>, Error> {
        (*self.bind_fn)(id, client)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::sync::Arc;

    use crate::test_protocol::{TestInterface, TestInterface2};
    use failure::Error;
    use fuchsia_async as fasync;
    use fuchsia_wayland_core::{Interface, IntoMessage};
    use fuchsia_zircon as zx;
    use parking_lot::Mutex;

    use crate::client::Client;
    use crate::object::RequestDispatcher;
    use crate::test_protocol::*;

    #[test]
    fn registry_bind() -> Result<(), Error> {
        // We'll pass this to our globals and verify that the right number of
        // messages are delivered.
        #[derive(Default)]
        struct Counts {
            interface_1_bind_count: usize,
            interface_2_bind_count: usize,
        }
        let counts: Arc<Mutex<Counts>> = Arc::new(Mutex::new(Default::default()));
        let mut registry = RegistryBuilder::new();

        {
            let counts = counts.clone();
            registry.add_global(TestInterface, move |_, _| {
                counts.lock().interface_1_bind_count += 1;
                Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
            });
        }
        {
            let counts = counts.clone();
            registry.add_global(TestInterface2, move |_, _| {
                counts.lock().interface_2_bind_count += 1;
                Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
            });
        }

        // Build the registry & verify initial counts.
        let registry = registry.build();
        assert_eq!(0, counts.lock().interface_1_bind_count);
        assert_eq!(0, counts.lock().interface_2_bind_count);

        // Bind to the globals.
        let (c1, _c2) = zx::Channel::create()?;
        let registry = Arc::new(Mutex::new(registry));
        let _executor = fasync::Executor::new();
        let mut client = Client::new(fasync::Channel::from_channel(c1)?, registry.clone());

        let receivers: Vec<Box<MessageReceiver>> = registry
            .lock()
            .globals
            .iter_mut()
            .map(|g| g.bind(0, &mut client).unwrap())
            .collect();
        for (id, r) in receivers.into_iter().enumerate() {
            client.add_object_raw(id as u32, r, &TestInterface::REQUESTS)?;
        }
        assert_eq!(1, counts.lock().interface_1_bind_count);
        assert_eq!(1, counts.lock().interface_2_bind_count);
        assert_eq!(0, client.get_object::<TestReceiver>(0)?.count());
        assert_eq!(0, client.get_object::<TestReceiver>(1)?.count());

        // Dispatch a message to each receiver.
        client.receive_message(TestMessage::Message1.into_message(0)?)?;
        client.receive_message(TestMessage::Message1.into_message(1)?)?;

        assert_eq!(1, counts.lock().interface_1_bind_count);
        assert_eq!(1, counts.lock().interface_2_bind_count);
        assert_eq!(1, client.get_object::<TestReceiver>(0)?.count());
        assert_eq!(1, client.get_object::<TestReceiver>(1)?.count());
        Ok(())
    }
}
