use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use defs::SkylaneError;
use object::{Object, ObjectId, DISPLAY_ID, SERVER_START_ID};
use sockets::Socket;
pub struct Bundle {
    socket: Socket,
    objects: Rc<RefCell<HashMap<ObjectId, Rc<RefCell<Box<Object>>>>>>,
}
impl Bundle {
        pub fn get_socket(&self) -> Socket {
        self.socket.clone()
    }
                                                pub fn get_next_available_client_object_id(&self) -> ObjectId {
        if let Some(max) = self.objects.borrow().keys().max() {
            if *max >= DISPLAY_ID {
                max.incremented()
            } else {
                DISPLAY_ID
            }
        } else {
            DISPLAY_ID
        }
    }
        pub fn get_next_available_server_object_id(&self) -> ObjectId {
        if let Some(max) = self.objects.borrow().keys().max() {
            if *max >= SERVER_START_ID {
                max.incremented()
            } else {
                SERVER_START_ID
            }
        } else {
            SERVER_START_ID
        }
    }
                                pub fn add_object(&mut self, id: ObjectId, object: Box<Object>) {
        self.objects.borrow_mut().insert(id, Rc::new(RefCell::new(object)));
    }
        pub fn add_next_client_object(&mut self, object: Box<Object>) -> ObjectId {
        let id = self.get_next_available_client_object_id();
        self.add_object(id, object);
        id
    }
        pub fn add_next_server_object(&mut self, object: Box<Object>) -> ObjectId {
        let id = self.get_next_available_server_object_id();
        self.add_object(id, object);
        id
    }
        pub fn remove_object(&mut self, id: ObjectId) {
        self.objects.borrow_mut().remove(&id);
    }
}
pub trait BundleInternal {
        fn new(socket: Socket) -> Self;
                    fn duplicate(&self) -> Self;
        fn get_handler(&self, object_id: ObjectId) -> Result<Rc<RefCell<Box<Object>>>, SkylaneError>;
}
impl BundleInternal for Bundle {
    fn new(socket: Socket) -> Self {
        Bundle {
            socket: socket,
            objects: Rc::new(RefCell::new(HashMap::new())),
        }
    }
    fn duplicate(&self) -> Self {
        Bundle {
            socket: self.socket.clone(),
            objects: self.objects.clone(),
        }
    }
    fn get_handler(&self, object_id: ObjectId) -> Result<Rc<RefCell<Box<Object>>>, SkylaneError> {
        if let Some(object) = self.objects.borrow().get(&object_id) {
            Ok(object.clone())
        } else {
            Err(SkylaneError::WrongObject { object_id: object_id })
        }
    }
}