/*****************************************************************************

File: Vector3i.h
Desc: A 3 dimensional integer vector with extended functionality
		
Date: 2005/01/01

Author: Wim Lemkens

*****************************************************************************/

#ifndef _VECTOR3IX_H_
#define _VECTOR3IX_H_

#include "Vector3i.h"

namespace Ogre {


class Vector3ix : public Vector3i {
public:
	/**
	 * The default constructor
	 * @post	this->x == 0
	 * @post	this->y == 0
	 * @post	this->z == 0
	 */
	Vector3ix(){
		x=0;
		y=0;
		z=0;
	}

	/**
	 * A constructor
	 * @param	int x
	 * 			The x-value to initialise the vector to
	 * @param	int y
	 * 			The y-value to initialise the vector to
	 * @param	int z
	 * 			The z-value to initialise the vector to
	 * @post	this->x == <x>
	 * @post	this->y == <y>
	 * @post	this->z == <z>
	 */
	Vector3ix(int x,int y,int z){
		this->x=x;
		this->y=y;
		this->z=z;
	}

	/**
	 * Returns the position below this one
	 * @return	Vector3ix(x,y+1,z)
	 * 			
	 */
	Vector3ix getBottom(){
		return Vector3ix(x,y+1,z);
	}

	/**
	 * Returns the position above this one
	 * @return	Vector3ix(x,y-1,z)
	 * 			
	 */
	Vector3ix getTop(){
		return Vector3ix(x,y-1,z);
	}

	/**
	 * Returns the position to the left of this one
	 * @return	Vector3ix(x-1,y,z)
	 * 			
	 */
	Vector3ix getLeft(){
		return Vector3ix(x-1,y,z);
	}

	/**
	 * Returns the position to the right of this one
	 * @return	Vector3ix(x+1,y,z)
	 * 			
	 */
	Vector3ix getRight(){
		return Vector3ix(x+1,y,z);
	}

	/**
	 * Operator for comparing Vector3ix
	 */
    inline bool operator == ( const Vector3ix& rkVector ) const
    {
        return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
    }

	/**
	 * Operator for comparing Vector3ix
	 */
    inline bool operator != ( const Vector3ix& rkVector ) const
    {
        return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
    }

    // arithmetic operations
    inline Vector3ix operator + ( const Vector3ix& rkVector ) const
    {
        Vector3ix kSum;

        kSum.x = x + rkVector.x;
        kSum.y = y + rkVector.y;
        kSum.z = z + rkVector.z;

        return kSum;
    }

    inline Vector3ix operator - ( const Vector3ix& rkVector ) const
    {
        Vector3ix kDiff;

        kDiff.x = x - rkVector.x;
        kDiff.y = y - rkVector.y;
        kDiff.z = z - rkVector.z;

        return kDiff;
    }

    inline Vector3ix operator * ( int fScalar ) const
    {
        Vector3ix kProd;

        kProd.x = fScalar*x;
        kProd.y = fScalar*y;
        kProd.z = fScalar*z;

        return kProd;
    }

    inline Vector3ix operator * ( const Vector3ix& rhs) const
    {
        Vector3ix kProd;

        kProd.x = rhs.x * x;
        kProd.y = rhs.y * y;
        kProd.z = rhs.z * z;

        return kProd;
    }

    inline Vector3ix operator / ( int fScalar ) const
    {
        assert( fScalar != 0.0 );

        Vector3ix kDiv;

        Real fInv = 1.0 / fScalar;
        kDiv.x = (int)(x * fInv);
        kDiv.y = (int)(y * fInv);
        kDiv.z = (int)(z * fInv);

        return kDiv;
    }

    inline Vector3ix operator / ( const Vector3ix& rhs) const
    {
        Vector3ix kDiv;

        kDiv.x = x / rhs.x;
        kDiv.y = y / rhs.y;
        kDiv.z = z / rhs.z;

        return kDiv;
    }


    inline Vector3ix operator - () const
    {
        Vector3ix kNeg;

        kNeg.x = -x;
        kNeg.y = -y;
        kNeg.z = -z;

        return kNeg;
    }

    inline friend Vector3ix operator * ( int fScalar, const Vector3ix& rkVector )
    {
        Vector3ix kProd;

        kProd.x = fScalar * rkVector.x;
        kProd.y = fScalar * rkVector.y;
        kProd.z = fScalar * rkVector.z;

        return kProd;
    }

    // arithmetic updates
    inline Vector3ix& operator += ( const Vector3ix& rkVector )
    {
        x += rkVector.x;
        y += rkVector.y;
        z += rkVector.z;

        return *this;
    }

    inline Vector3ix& operator -= ( const Vector3ix& rkVector )
    {
        x -= rkVector.x;
        y -= rkVector.y;
        z -= rkVector.z;

        return *this;
    }

    inline Vector3ix& operator *= ( int fScalar )
    {
        x *= fScalar;
        y *= fScalar;
        z *= fScalar;
        return *this;
    }

    inline Vector3ix& operator *= ( const Vector3ix& rkVector )
    {
        x *= rkVector.x;
        y *= rkVector.y;
        z *= rkVector.z;

        return *this;
    }

    inline Vector3ix& operator /= ( int fScalar )
    {
        assert( fScalar != 0.0 );

        Real fInv = 1.0 / fScalar;

        x *= (int)fInv;
        y *= (int)fInv;
        z *= (int)fInv;

        return *this;
    }

    inline Vector3ix& operator /= ( const Vector3ix& rkVector )
    {
        x /= rkVector.x;
        y /= rkVector.y;
        z /= rkVector.z;

        return *this;
    }
};

} // namespace Ogre
#endif //_VECTOR3I_H_
