#![allow(non_snake_case)]

extern crate rand;
extern crate MBrane;

use rand::Rng;
use MBrane::Vector::Vector2D::*;

#[test]
fn vector2d_initialization() {
    let mut rng = rand::thread_rng();

    let rx = rng.gen::<f64>();
    let ry = rng.gen::<f64>();

    let vector = Vector2D { X: rx, Y: ry };

    assert_eq!(rx, vector.X);
    assert_eq!(ry, vector.Y);
}

#[test]
fn vector2d_new_initialization() {
    let mut rng = rand::thread_rng();

    let rx = rng.gen::<f64>();
    let ry = rng.gen::<f64>();

    let vector = Vector2D { X: rx, Y: ry };
    let new_vector = vector.New(rx, ry);

    assert_eq!(rx, new_vector.X);
    assert_eq!(ry, new_vector.Y);
}

#[test]
fn vector2d_magnitude() {
    let mut rng = rand::thread_rng();

    let rx = rng.gen::<f64>();
    let ry = rng.gen::<f64>();

    let rresult = ((rx * rx) + (ry * ry)).sqrt();

    let vector = Vector2D { X: rx, Y: ry };

    let result: f64 = vector.Magnitude();

    assert_eq!(rresult, result);
}

#[test]
fn vector2d_normalization() {
    let mut rng = rand::thread_rng();

    let rx = rng.gen::<f64>();
    let ry = rng.gen::<f64>();

    let rxres = rx / ((rx * rx) + (ry * ry)).sqrt();
    let ryres = ry / ((rx * rx) + (ry * ry)).sqrt();

    let mut vector = Vector2D { X: rx, Y: ry };

    vector.Normalize();

    assert_eq!(rxres, vector.X);
    assert_eq!(ryres, vector.Y);
}

#[test]
fn vector2d_addition() {
    let mut rng = rand::thread_rng();

    let rx_lhs = rng.gen::<f64>();
    let ry_lhs = rng.gen::<f64>();

    let rx_rhs = rng.gen::<f64>();
    let ry_rhs = rng.gen::<f64>();

    let rx_result = rx_lhs + rx_rhs;
    let ry_result = ry_lhs + ry_rhs;

    let lhs = Vector2D {
        X: rx_lhs,
        Y: ry_lhs,
    };
    let rhs = Vector2D {
        X: rx_rhs,
        Y: ry_rhs,
    };

    let result = lhs + rhs;

    assert_eq!(rx_result, result.X);
    assert_eq!(ry_result, result.Y);
}

#[test]
fn vector2d_substraction() {
    let mut rng = rand::thread_rng();

    let rx_lhs = rng.gen::<f64>();
    let ry_lhs = rng.gen::<f64>();

    let rx_rhs = rng.gen::<f64>();
    let ry_rhs = rng.gen::<f64>();

    let rx_result = rx_lhs - rx_rhs;
    let ry_result = ry_lhs - ry_rhs;

    let lhs = Vector2D {
        X: rx_lhs,
        Y: ry_lhs,
    };
    let rhs = Vector2D {
        X: rx_rhs,
        Y: ry_rhs,
    };

    let result = lhs - rhs;

    assert_eq!(rx_result, result.X);
    assert_eq!(ry_result, result.Y);
}

#[test]
fn vector2d_multiplication() {
    let mut rng = rand::thread_rng();

    let rx_lhs = rng.gen::<f64>();
    let ry_lhs = rng.gen::<f64>();

    let rx_rhs = rng.gen::<f64>();
    let ry_rhs = rng.gen::<f64>();

    let rx_result = rx_lhs * rx_rhs;
    let ry_result = ry_lhs * ry_rhs;

    let lhs = Vector2D {
        X: rx_lhs,
        Y: ry_lhs,
    };
    let rhs = Vector2D {
        X: rx_rhs,
        Y: ry_rhs,
    };

    let result = lhs * rhs;

    assert_eq!(rx_result, result.X);
    assert_eq!(ry_result, result.Y);
}

#[test]
fn vector2d_division() {
    let mut rng = rand::thread_rng();

    let rx_lhs = rng.gen::<f64>();
    let ry_lhs = rng.gen::<f64>();

    let rx_rhs = rng.gen::<f64>();
    let ry_rhs = rng.gen::<f64>();

    let rx_result = rx_lhs / rx_rhs;
    let ry_result = ry_lhs / ry_rhs;

    let lhs = Vector2D {
        X: rx_lhs,
        Y: ry_lhs,
    };
    let rhs = Vector2D {
        X: rx_rhs,
        Y: ry_rhs,
    };

    let result = lhs / rhs;

    assert_eq!(rx_result, result.X);
    assert_eq!(ry_result, result.Y);
}
