use bevy::prelude::*;

use super::{Vector3, VectorComponent};

#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]
pub struct Basis<T: VectorComponent> {
    pub x: Vector3<T>,
    pub y: Vector3<T>,
    pub z: Vector3<T>,
}

impl<T: VectorComponent> Default for Basis<T> {
    fn default() -> Self {
        Self {
            x: Vector3::x(),
            y: Vector3::y(),
            z: Vector3::z(),
        }
    }
}

impl<T: VectorComponent> Basis<T> {
    pub fn identity() -> Self {
        Self::default()
    }

    pub fn inverse(&self) -> Self {
        Self {
            x: self.x * -T::one(),
            y: self.y * -T::one(),
            z: self.z * -T::one(),
        }
    }

    pub fn transform(&self, point: Vector3<T>) -> Vector3<T> {
        self.x * point.x + self.y * point.y + self.z * point.z
    }

    pub fn inverse_transform(&self, point: Vector3<T>) -> Vector3<T> {
        self.inverse().transform(point)
    }
}
