use crate::{Bivector, Rotor, Vector};

use data_stream::{FromStream, ToStream, from_stream, numbers::EndianSettings, to_stream};

use std::io::{Read, Result, Write};

impl<S: EndianSettings, T: ToStream<S>> ToStream<S> for Vector<T> {
    fn to_stream<W: Write>(&self, writer: &mut W) -> Result<()> {
        to_stream(&self.x, writer)?;
        to_stream(&self.y, writer)?;
        to_stream(&self.z, writer)?;

        Ok(())
    }
}

impl<S: EndianSettings, T: FromStream<S>> FromStream<S> for Vector<T> {
    fn from_stream<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(Self {
            x: from_stream(reader)?,
            y: from_stream(reader)?,
            z: from_stream(reader)?,
        })
    }
}

impl<S: EndianSettings, T: ToStream<S>> ToStream<S> for Bivector<T> {
    fn to_stream<W: Write>(&self, writer: &mut W) -> Result<()> {
        to_stream(&self.xy, writer)?;
        to_stream(&self.xz, writer)?;
        to_stream(&self.yz, writer)?;

        Ok(())
    }
}

impl<S: EndianSettings, T: FromStream<S>> FromStream<S> for Bivector<T> {
    fn from_stream<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(Self {
            xy: from_stream(reader)?,
            xz: from_stream(reader)?,
            yz: from_stream(reader)?,
        })
    }
}

impl<S: EndianSettings, T: ToStream<S>> ToStream<S> for Rotor<T> {
    fn to_stream<W: Write>(&self, writer: &mut W) -> Result<()> {
        to_stream(&self.scalar, writer)?;
        to_stream(&self.xy, writer)?;
        to_stream(&self.xz, writer)?;
        to_stream(&self.yz, writer)?;

        Ok(())
    }
}

impl<S: EndianSettings, T: FromStream<S>> FromStream<S> for Rotor<T> {
    fn from_stream<R: Read>(reader: &mut R) -> Result<Self> {
        Ok(Self {
            scalar: from_stream(reader)?,
            xy: from_stream(reader)?,
            xz: from_stream(reader)?,
            yz: from_stream(reader)?,
        })
    }
}
