use embedded_hal::blocking::i2c::{Write, WriteRead};

#[derive(Debug)]
pub enum Error<RE, WE> {
    ReadError(RE),
    WriteError(WE),
}

pub trait ErrorType {
    type Error;
}

pub enum Variant {
    B,
    B01,
    B10,
    B11,
}

impl Variant {
    fn address(&self) -> u8 {
        match self {
            Variant::B => 0b0100_010,
            Variant::B01 => 0b0100_011,
            Variant::B10 => 0b0100_100,
            Variant::B11 => 0b0100_101,
        }
    }
}

pub struct Fusb302<I2C> {
    i2c: I2C,
    variant: Variant,
}

impl<I2C> ErrorType for Fusb302<I2C>
where
    I2C: Write + WriteRead,
{
    type Error = Error<<I2C as WriteRead>::Error, <I2C as Write>::Error>;
}

impl<I2C> Fusb302<I2C>
where
    I2C: Write + WriteRead,
{
    pub fn new(i2c: I2C, variant: Variant) -> Self {
        Self { i2c, variant }
    }

    pub fn release(self) -> I2C {
        self.i2c
    }

    pub fn reset(&mut self) -> Result<(), <Self as ErrorType>::Error> {
        self.i2c
            .write(self.variant.address(), &[0x0c, 0b1])
            .map_err(|err| Error::WriteError(err))
    }
}
