#include "Vector.h"

#include <cmath>
#include <stdexcept>

Vector::Vector(Primitive p)
{
    switch(p)
    {
    case Primitive::UNIT_X:
        mX = 1.0;
        break;
    case Primitive::UNIT_Y:
        mY = 1.0;
        break;
    case Primitive::UNIT_Z:
        mZ = 1.0;
        break;
    case Primitive::NEGATIVE_X:
        mX = -1.0;
        break;
    case Primitive::NEGATIVE_Y:
        mY = -1.0;
        break;
    case Primitive::NEGATIVE_Z:
        mZ = -1.0;
        break;
    }
}

Vector::Vector(double x, double y, double z)
    :   mX(x),
        mY(y),
        mZ(z)
{
}

Vector::~Vector()
{
};

void Vector::reverseDirection()
{
    (*this) *= -1.0;
}

double Vector::getX() const
{
    return mX;
}

double Vector::getY() const
{
    return mY;
}

double Vector::getZ() const
{
    return mZ;
}

double Vector::getLength() const
{
    return std::sqrt(mX * mX + mY * mY + mZ * mZ);
}

double Vector::dotProduct(const Vector& v) const
{
    return mX * v.mX + mY * v.mY + mZ * v.mZ;
}

Vector Vector::crossProduct(const Vector& v) const
{
    return Vector(v.mY * mZ - v.mZ * mY, v.mZ * mX - v.mX * mZ, v.mX * mY - v.mY * mX);
}

Vector Vector::getNormalized() const
{
    const auto length = getLength();
    if (length == 0.0)
    {
        throw std::logic_error("Divide by zero getting normalizing vector");
    }
    return Vector(mX / length, mY / length, mZ / length);
}

void Vector::scale(double x, double y, double z)
{
    mX = x * mX;
    mY = y * mY;
    mZ = z * mZ;
}
