//
// Tools_Vertex_Selection.h
//
// Created by Richard Rice - 27/01/04
// 
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_VERTEX_SELECTION_H__
#define __TOOLS_VERTEX_SELECTION_H__


#include "Tools_Undo.h"
#include "Core/Asura_Maths.h"
#include "Misc/list_tem.hpp"
#include "Misc/Tools_Polygon_Selection.h"
///////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////
/*
For keeping track of the selected vertices in one module. Also logs selection/deselection for undo
*/
class VertexSelectionList : public ItemSelectionList
{
public :
	VertexSelectionList(int iModule,int iNumPoly);

private :
	int m_iModuleIndex;

	virtual void ItemBeingSelected(int iIndex);
	virtual void ItemBeingDeselected(int iIndex);
};

///////////////////////////////////////////////////////////////////////////////////////
struct VertexSelectionUndoData
{
	enum UndoType
	{
		UndoType_Added,
		UndoType_Removed,
		UndoType_ForceInt = 0xffffffff,
	};
	
	enum UndoType m_eUndoType;
	int m_iModuleIndex;
	int m_iVertexIndex;
};

class VertexSelectionUndo : public FixedSizeUndo
{
public :
	VertexSelectionUndo()
	:FixedSizeUndo(10000,sizeof(VertexSelectionUndoData)){}

	void ProcessUndoData(void*);
	
	void LogVertexSelected(int iModule,int iVert);
	void LogVertexDeselected(int iModule,int iVert);
};
///////////////////////////////////////////////////////////////////////////////////////

//simple structure for identifying a given vertex from its module and vertex index
struct ModuleVertexPair
{
	ModuleVertexPair(){};
	ModuleVertexPair(int m,int v){iModuleIndex=m,iVertexIndex=v;}

	bool operator == (const ModuleVertexPair& v){return v.iModuleIndex==iModuleIndex && v.iVertexIndex==iVertexIndex;}
	bool operator != (const ModuleVertexPair& v){return v.iModuleIndex!=iModuleIndex || v.iVertexIndex!=iVertexIndex;}
	
	int iModuleIndex;
	int iVertexIndex;
};

///////////////////////////////////////////////////////////////////////////////////////

enum VertexSelectionMode
{
	VSelectionMode_Vertex,
	VSelectionMode_Polygon,
	VSelectionMode_Object,
};

#define VertexSelectionUpdate_Standard 0
#define VertexSelectionUpdate_NoMouseSelection 1
#define VertexSelectionUpdate_NoSelection 2

class Tools_Vertex_Selection
{
public : 
	static void Initialise();
	static void Shutdown();
	
	static void Activate();
	static void Deactivate();

	static void Update(int iUpdateMode = VertexSelectionUpdate_Standard);
	static void Render();

//member variables
	static int s_iNumberOfModules;
	static int s_iNumSelectedModules;//number of moudules with at least 1 vertex selected

	static bool IsActive(){return s_bActive;}

	static bool s_bShowSelection; 
private :
	static bool s_bSelectionLocked;
	static bool s_bShowLooseVertices;
	static int s_iSelectionMode;//value from enum VertexSelectionMode
	static int s_iSelectionModeListOffset;//just used since I need a paramater for the list overlay thingy

	static Asura_Vector_2 s_xSelectionOverlayPosition;
	static bool s_bSelectionOverlayOpen;
	static u_int s_uSelectionOverlayMinimised;
	static VertexSelectionList** s_ppxSelection;
	static VertexSelectionUndo s_xSelectionUndo;
	static int s_iCurrentIterationModule;


	//used to determine whether the mouse button was pressed to start polygon selection
	//(allows use of non-debounced button , except when it would be underiable)
	static bool s_bButtonDownForSelection;
	static ModuleVertexPair s_xHighlitVertex;//vertex mouse is currently over
	static PolygonID s_xHighlitPolygon;//polygon mouse is currently over

	static bool s_bActive;
public :

//selection/deselection functions
	static void SelectVertex(int iModuleIndex,int iVertexIndex); 
	static void DeselectVertex(int iModuleIndex,int iVertexIndex);
	static void SelectPolygon(int iModuleIndex,int iPolygonIndex); 
	static void DeselectPolygon(int iModuleIndex,int iPolygonIndex);
	static void SelectObject(int iModuleIndex); 
	static void DeselectObject(int iModuleIndex);
	static void SelectAll();
	static void DeselectAll();

	static int GetNumberOfSelectedVertices();


//iterating through the selection
//(note this is a bit dubious since only 1 iteration can happen at a time... but I haven't needed
//to run several concurrent iterations yet)
	static void StartIteration();
	static bool GetNextSelected(ModuleVertexPair* pxVertex);

	static bool IsSelected(const ModuleVertexPair& xVertex);
	static int CountSelectedInModule(int iModuleIndex);

//selection overlay functions
	static void ToggleSelectionOverlay(void);
	static bool SelectionOverlayIsOn(void);
	static void CreateSelectionOverlay(void);
	static void CloseSelectionOverlay();
	
	static bool GetVertexUnderMouse(ModuleVertexPair& xVertex);
	static bool GetHighlitVertex(ModuleVertexPair& xVertex);

//handling changes that result in changes to the number of vertices
	static void HandleVertexConversion(int iModuleIndex,int* VertConv);
	static void DeleteModule(int iModuleIndex);
//Notifies vertex selection that the mesh has been replaced by another that may or may not be completely different
	static void HandleMeshChange(int iModuleIndex);

	static void ClearUndo(){s_xSelectionUndo.FlushUndoBuffer();}

private :

//highlighting polygons
	static void HighlightSelection();//red outline
   	static void HighlightVertex(ModuleVertexPair& xVertex);//pulsing white outline
   	static void HighlightPolygon(PolygonID& xPolygon);//pulsing white outline

	static void Undo();	
	static void Redo();	

	//checks for keyboard shortcuts being pressed
	static void HandleKeyboard();
	//for handling general vertex selection using the mouse
	static void HandleMouseSelection();

	//loads/saves data for this mode
	static void TransferModeData(int mode);



	friend class VertexSelectionList;

};



#endif //__TOOLS_VERTEX_SELECTION_H__
