#ifndef _POVMESH_H
#define _POVMESH_H

#include <QTextStream>

template <class T> class Vector3d
{
	public:
		Vector3d(T t1, T t2, T t3) : X(t1), Y(t2), Z(t3) {}
		const T& x() const {return X;}
		const T& y() const {return Y;}
		const T& z() const {return Z;}

        Vector3d operator * (double x) const
        {
            Vector3d <T> ret(*this);
            ret.X *= x;
            ret.Y *= x;
            ret.Z *= x;

            return ret;
        }

        Vector3d operator + (const Vector3d& second) const
        {
            Vector3d <T> ret(*this);
            ret.X += second.X;
            ret.Y += second.Y;
            ret.Z += second.Z;

            return ret;
        }

        Vector3d operator - (const Vector3d& second) const
        {
            return *this + (second * -1);
        }

		T& x() {return X;}
		T& y() {return Y;}
		T& z() {return Z;}

        QTextStream& toQTextStream(QTextStream & ts, double fac=1) const
        {
            if (fac != 1)
                ts << "<" << X/fac << ", " << Y/fac << ", " << Z/fac << ">";
            else
                ts << "<" << X << ", " << Y << ", " << Z << ">";

            return ts;
        }

	private:
		T X;
		T Y;
		T Z;
};



class POVMesh2
{
public:
	typedef Vector3d <double> dvector3d;
	typedef Vector3d <unsigned int> ivector3d;

    //typedef std::list <dvector3d> PointListT;
    typedef QHash <dvector3d, int> PointHashT;
    typedef QList <dvector3d> PointListT;
    typedef QList <ivector3d> FacesListT;

    POVMesh2();

    int addVertice(double x, double y, double z);
    int addFace(unsigned int v1, unsigned int v2, unsigned int v3) {Faces.push_back(ivector3d(v1,v2,v3)); return Faces.size()-1;}
    void setScale(double s) {Scale = s;}
    friend QTextStream &operator<<(QTextStream & ts, POVMesh2& m);
    double getMaxSize() const;
    void moveBy(dvector3d v);
    dvector3d center() const;
    void setCenter(dvector3d c = {0,0,0});
    dvector3d normalize(double maxsize = 1);
private:
    void extendBounds(double x, double y, double z);
    void resetBounds(bool recalc = false);

    PointHashT VerticesHash;
	PointListT Vertices;
	FacesListT Faces;
    double Scale = 1;
    double Maxs[3];
    double Mins[3];
    int Dups;
};

bool operator== (const POVMesh2::dvector3d& left, const POVMesh2::dvector3d& right);
uint qHash(const POVMesh2::dvector3d& key, uint seed);
QDebug& operator<< (QDebug&, POVMesh2::dvector3d);

#endif
