#include <cmath>

#include "client/math/Vector.h"

Vector::Vector() : x(0), y(0), z(0)
{
}

Vector::Vector(float ix, float iy, float iz) : x(ix), y(iy), z(iz)
{
}

float Vector::getX() const
{
    return x;
}

float Vector::getY() const
{
    return y;
}

float Vector::getZ() const
{
    return z;
}

void Vector::setX(float ix)
{
    x = ix;
}

void Vector::setY(float iy)
{
    y = iy;
}

void Vector::setZ(float iz)
{
    z = iz;
}

void Vector::set(float ix, float iy, float iz)
{
    x = ix;
    y = iy;
    z = iz;
}

void Vector::setInverse(const Vector& v)
{
    x = -v.x;
    y = -v.y;
    z = -v.z;
}

void Vector::setMul(const Vector& v, float f)
{
    x = v.x * f;
    y = v.y * f;
    z = v.z * f;
}

void Vector::setAngles(float lengthAngle, float widthAngle)
{
    lengthAngle = lengthAngle * M_PI / 180.0f;
    widthAngle = widthAngle * M_PI / 180.0f;
    x = cosf(widthAngle) * sinf(lengthAngle);
    y = sinf(widthAngle);
    z = cosf(widthAngle) * cosf(lengthAngle); 
}


void Vector::add(const Vector& v)
{
    x += v.x;
    y += v.y;
    z += v.z;
}

void Vector::sub(const Vector& v)
{
    x -= v.x;
    y -= v.y;
    z -= v.z;
}

void Vector::mul(float f)
{
    x *= f;
    y *= f;
    z *= f;
}

void Vector::addMul(const Vector& v, float f)
{
    x += v.x * f;
    y += v.y * f;
    z += v.z * f;
}


void Vector::cross(float ix, float iy, float iz)
{
    set(y * iz - z * iy, z * ix - x * iz, x * iy - y * ix);
}

void Vector::cross(const Vector& v)
{
    set(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
}

void Vector::normalize()
{
    float f = 1.0f / sqrtf(squareLength());
    x *= f;
    y *= f;
    z *= f;
}

float Vector::squareLength() const
{
    return x * x + y * y + z * z;
}

float Vector::dot(const Vector& v) const
{
    return x * v.x + y * v.y + z * v.z;
}

float Vector::dotInverse(const Vector& v) const
{
    return x * (-v.x) + y * (-v.y) + z * (-v.z);
}

std::ostream& operator<<(std::ostream& os, const Vector& v)
{
    return os << "Vector(x = " << v.getX() << ", y = " << v.getY() << ", z = " << v.getZ() << ")";
}