#pragma once

#include "winding.h"
#include "Face.h"

class FaceVertexId
{
		std::size_t m_face;
		std::size_t m_vertex;

	public:
		FaceVertexId (std::size_t face, std::size_t vertex) :
			m_face(face), m_vertex(vertex)
		{
		}

		std::size_t getFace () const
		{
			return m_face;
		}
		std::size_t getVertex () const
		{
			return m_vertex;
		}
};

class SelectableEdge
{
		Vector3 getEdge () const
		{
			const Winding& winding = getFacePtr()->getWinding();
			return vector3_mid(winding[m_faceVertex.getVertex()].vertex, winding[winding.next(m_faceVertex.getVertex())].vertex);
		}

	public:
		Faces& m_faces;
		FaceVertexId m_faceVertex;

		SelectableEdge (Faces& faces, FaceVertexId faceVertex) :
			m_faces(faces), m_faceVertex(faceVertex)
		{
		}
		SelectableEdge& operator= (const SelectableEdge& other)
		{
			m_faceVertex = other.m_faceVertex;
			return *this;
		}

		const Face* getFacePtr () const
		{
			return m_faces[m_faceVertex.getFace()].get();
		}

		const Face& getFace () const
		{
			return *m_faces[m_faceVertex.getFace()];
		}

		void testSelect (SelectionTest& test, SelectionIntersection& best)
		{
			test.TestPoint(getEdge(), best);
		}
};

class SelectableVertex
{
		Vector3 getVertex () const
		{
			return getFace().getWinding()[m_faceVertex.getVertex()].vertex;
		}

	public:
		Faces& m_faces;
		FaceVertexId m_faceVertex;

		SelectableVertex (Faces& faces, FaceVertexId faceVertex) :
			m_faces(faces), m_faceVertex(faceVertex)
		{
		}
		SelectableVertex& operator= (const SelectableVertex& other)
		{
			m_faceVertex = other.m_faceVertex;
			return *this;
		}

		Face& getFace () const
		{
			return *m_faces[m_faceVertex.getFace()];
		}

		void testSelect (SelectionTest& test, SelectionIntersection& best)
		{
			test.TestPoint(getVertex(), best);
		}
};
