
use crate::master::core::EtherCATMaster;
use crate::slave::core::Slave;
use std::cell::UnsafeCell;
use std::ops::Index;

pub struct Indexable<'a> {
    master: &'a EtherCATMaster,

    cache: UnsafeCell<Vec<Slave>>,
}

impl<'a> Indexable<'a> {

    pub(crate) fn new(master: &'a EtherCATMaster) -> Self {
        let count = master.slave_count() as usize;
        let mi = master.index();

        let mut v = Vec::with_capacity(count + 1);
        for i in 0..=count {
            v.push(Slave::new(mi, i as u16));
        }
        Self {
            master,
            cache: UnsafeCell::new(v),
        }
    }

    pub fn len(&self) -> usize {
        self.master.slave_count() as usize
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl<'a> Index<usize> for Indexable<'a> {
    type Output = Slave;

    fn index(&self, idx: usize) -> &Self::Output {

        let v = unsafe { &*self.cache.get() };
        &v[idx]
    }
}

impl<'a> Index<u16> for Indexable<'a> {
    type Output = Slave;

    fn index(&self, idx: u16) -> &Self::Output {
        let v = unsafe { &*self.cache.get() };
        &v[idx as usize]
    }
}

pub trait MasterIndexExt {

    fn indexable(&self) -> Indexable<'_>;
}

impl MasterIndexExt for EtherCATMaster {
    fn indexable(&self) -> Indexable<'_> {
        Indexable::new(self)
    }
}
