///////////////////////////////////////////////////////////////////////////////
//
// File   : ToolsAVP_Mode_Waypointing.h
// Author : Andy Tate
// Date   : 4-Jun-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __TOOLSAVP_MODE_WAYPOINTING_H__
#define __TOOLSAVP_MODE_WAYPOINTING_H__

// Include Files

#include "Waypointing/Tools_Mode_Waypointing.h"

// asura
#include "Core/Asura_LinkList.h"

// Forward Declarations

class Asura_Attractor_Compiled;
class AVP_ServerNode_GS2Node;
class AVP_Tools_Waypoint_Searcher;
class Tools_Attractor;
class Tools_Attractor_Node;

////////////////////////////////////////////////////////////////////////////////
// 
// ToolsAVP_Mode_Waypointing
//
////////////////////////////////////////////////////////////////////////////////

enum TOOLSAVP_NAVVERTEX_FLAGS
{
	TOOLS_NAVVERTEX_FLAG_LIFT_UDW = TOOLS_NAVVERTEX_FLAG_PROJECT_SPECIFIC
};

enum TOOLSAVP_CONNECTION_FLAG
{
    TOOLSAVP_CONNECTION_FLAG_TRANSITION = TOOLS_CONNECTION_FLAG_PROJECT_SPECIFIC // 0x01000000
};

class ToolsAVP_Mode_Waypointing : public Tools_Mode_Waypointing
{
    typedef Tools_Mode_Waypointing PARENT;

    friend class ToolsAVP_Waypoint_Analysis;
    friend class AVP_Chunk_Navigation;

public:
	ToolsAVP_Mode_Waypointing();

	static void GenerateExtraWaypointingData();

	static void VerifyWaypointsForLOF();

protected:
    virtual void InitialiseMode();
    virtual void ShutdownMode();
    virtual void Update();
    virtual void RenderWorld_PostToneMap();

    virtual void TransferToolsModeData( const int iMode, Tools_ModeDataFile& xFile );

    virtual Tools_Waypoint_Analysis* CreateWaypointAnalysis();

	virtual Tools_Waypoint_Object* CreateUserWaypointToolsObject( Asura_AI_Navigation_System::UserDefinedWaypoint* pxUDW );

    virtual bool GenerateWaypointsSingleStep( int iPhase, bool& bFinished );

    virtual bool InitialiseAndAllocateStorage();
    virtual bool CreateWaypointingPhysicsObjects();
    virtual void DestroyWaypointingPhysicsObjects();
	virtual bool AddUserDefinedNewWaypoint( const Tools_Waypoint_Object* const pxUserWaypoint );
    virtual bool CullWaypointsBySize();
	virtual bool CullRedundantWaypoints();
    virtual bool CullPhysicallyInvalidWaypoints();
    virtual bool GenerateWaypointLinks();
    virtual bool CullRedundantLinks();
    virtual bool MakeAllLinksTwoWay();
    virtual bool CullAndFlagLinkWithPhysics( u_int& uFlags,
                                             const Asura_Vector_3& xStart,
                                             const Asura_Vector_3& xStartNormal,
                                             const int iStartWPIndex,
                                             const Asura_Vector_3& xFinish,
                                             const Asura_Vector_3& xFinishNormal,
                                             const int iFinishWPIndex );
	virtual bool CullOneWayLinksWithNoReturn();
    virtual bool CalculateWaypointZoneIDs();

    virtual void RenderLinksHelpText( float& fX, float& fY ) const;
    virtual void RenderLinks() const;
    virtual void RenderWaypoints() const;
	virtual void RenderTestLinks() const;
	virtual void RenderTestWaypoints() const;
	virtual void RenderWaypointNormals() const;
    virtual void GetLinkColour( const unsigned int uFlags, const bool bTwoWayLink, Asura_Vector_3& xStartColour, Asura_Vector_3& xEndColour ) const;
    virtual void GetWaypointColour( const unsigned int uFlags, int& iColour ) const;
	virtual void RenderWaypointInfo( const int iWPIndex, float& fPrintX, float& fPrintY ) const;

	virtual int  GetFlagsForNewWaypoint( const int iPolyFlags, const Asura_Vector_3& xPolyNormal ) const;
	static  bool StaticIsFloorPoly( const int iPolyFlags, const Asura_Vector_3& xFaceNormal );
	static  bool StaticIsCeilingPoly( const Asura_Vector_3& xFaceNormal );
	static  bool StaticIsWallPoly( const int iPolyFlags, const Asura_Vector_3& xFaceNormal );
	// Not using slope polys in AVP3.
    virtual bool IsSlopePoly( const Asura_Vector_3& xFaceNormal )   const { return false; }
    virtual bool IsCeilingPoly( const Asura_Vector_3& xFaceNormal ) const;
    virtual bool IsWallPoly( const Asura_Vector_3& xFaceNormal )	const;

    virtual Asura_Char* GetPhaseName( const int iPhase );

private:
	// Do not define these functions!
	ToolsAVP_Mode_Waypointing(const ToolsAVP_Mode_Waypointing& xOther);
	ToolsAVP_Mode_Waypointing& operator=(const ToolsAVP_Mode_Waypointing& xOther);

    void CreateAVPOverlay();
    void DestroyAVPOverlay();
	static void ToggleAVPWaypointingOverlay();
	static bool AVPWaypointingOverlayIsOn();

    // Adds the correct flagging for waypoints (alien/humanoid, etc).
    bool InitialiseStandardBB();
    bool FlagWaypointsForActorType();
	bool AddGS2Waypoints();
	bool AddGS2Waypoint( const AVP_ServerNode_GS2Node& xGS2Node, const int iStructureType );
	bool AddEnvHookWaypoints();
	bool AddEnvHookWaypoint( const Asura_Vector_3& xPosition, const Asura_Vector_3& xNormal );
	bool AddPredatorJumpWaypoints();
	bool AddPredJumpWaypoint( const Asura_Vector_3& xPosition, const Asura_Vector_3& xNormal );
	bool AddAlienJumpWaypoints();
	bool AddAlienJumpWaypoint( const Asura_Vector_3& xPosition, const Asura_Vector_3& xNormal, bool bJumpOver );
	bool AddJumpLinks();
	bool AddGS2Links();
	bool AddEnvHookLinks();
	bool AddPredatorJumpLinks();
	bool AddAlienJumpLinks();
	bool AddLiftUDWLinks();
	Tools_Nav_Vertex* FindGS2Waypoint( const AVP_ServerNode_GS2Node& xGS2Node ) const;
	Tools_Nav_Vertex* FindEnvHookWaypoint( const Asura_Vector_3& xPosition, const Asura_Vector_3* pxNormal = NULL ) const;
	Tools_Nav_Vertex* FindPredatorJumpWaypoint( const Asura_Vector_3& xPosition, int& iWPIndex ) const;
	Tools_Nav_Vertex* FindAlienJumpWaypoint( const Asura_Vector_3& xPosition, int& iWPIndex, bool bJumpOver ) const;
	void FindNearestEnvHookNodePair( const Tools_Attractor* pxBaseAttractor, const Tools_Attractor* pxLinkedAttractor,
									 const Tools_Attractor_Node*& pxBaseNode, const Tools_Attractor_Node*& pxLinkedNode, float& fDistance );
	int GetWaypointIndex( const Tools_Nav_Vertex* pxWaypoint ) const;
    bool FlagTransitionLinks();
    bool CullOverlappingNonTransitionLinks();
    bool CullTransitionLinksUsingDistanceFromPlanes();
    bool CullLessDirectTransitionLinks();
    void EnumerateLinksOntoThisSurface( const Tools_Nav_Vertex& xBaseWaypoint, const Tools_Nav_Vertex& xSurfaceWaypoint, const bool bSurfaceIsConcave,
                                        int& iLinkCount, int* piLinkIndices );
    void CalculateLinkAngleScores( const Tools_Nav_Vertex& xBaseWaypoint, const Tools_Nav_Vertex& xSurfaceWaypoint, const bool bSurfaceIsConcave,
                                   const int iLinkCount, const int* const piLinkIndices,
                                   float* pfLinkAngleScores );
    void CalculateLinkDistanceScores( const Tools_Nav_Vertex& xBaseWaypoint,
                                      const int iLinkCount, const int* const piLinkIndices,
                                      float* pfLinkDistanceScores );
    void CalculateAcceptableScores( const int iLinkCount, float* pfLinkAngleScores, float* pfLinkDistanceScores );
    bool UnflagTransitionLinks();
    // Adds the correct flagging for transition links (med/high mobility, etc).
    bool FinalFlagTransitionLinks();
    bool AddFloorCeilingJumpLinks();
    bool AddCeilingFloorFallLinks();
    bool AddWallWallJumpLinks();
	bool RemoveHumanoidFlagFromInvalidOneWayLinks();

	bool ValidatePredatorJumpTest(const Asura_Vector_3& xFromPosition, const Asura_Vector_3& xToPosition) const;

    static void AVPAABBTreePerBinSizeTestCallback( u_int uIndex );
    static bool AVPMoveToDestination( const Asura_Vector_3& xStart, const Asura_Vector_3& xFinish,
                                      const Asura_Vector_3& xDestinationNormal,
                                      const Asura_Vector_3& xAllowedOffsetVector,
                                      const bool bIsAlienRoute, const bool bIsTransitionLink, const bool bIsConcave,
                                      Asura_Physics_Object* pxPhysicsObject, float& fMaxFallDistance );

    static bool SourceWaypointNormalIsValidForAttractor( const Asura_Attractor_Compiled& xAttractor, const float fAttractorAngle, const Tools_Nav_Vertex& xSourceWaypoint );
    static bool TargetWaypointNormalIsValidForAttractor( const Asura_Attractor_Compiled& xAttractor, const float fAttractorAngle,
                                                         const Tools_Nav_Vertex& xSourceWaypoint, const Tools_Nav_Vertex& xTargetWaypoint );
    static bool FindAttractorAngle( const Asura_Attractor_Compiled& xAttractor, float& fAngle );
    static bool FindAdjacentPolyVector( const Asura_Attractor_Compiled& xAttractor, Asura_Vector_3& xPolyVector );

    static void CreateAttractorWorldMatrix( const Asura_Vector_3& xAttractorNormal, const Asura_Vector_3& xAttractorAxis, Asura_Matrix_3x3& xAttractorMatrix );
    static void GetPolyNormal( const u_int uFaceID, Asura_AVector3& xPolyNormal );
    static void CalculateObjectSpaceAngVelocity( const Asura_Matrix_3x3& xCurrentOrientation, const Asura_Vector_3& xDesiredDirection, Asura_Angle& fAngVelocity );

    static void AddLastRouteToFailedRoutes( const Asura_Vector_3& xStartPosition, const Asura_Vector_3& xFinishPosition );

    static void AVPCalculateWaypointVolumeThreadFunction( const void* pParams );
    static bool FloodFillWaypointGraph( const int iStartWaypointIndex, const u_short usZoneID );

	static bool GetSurfaceNormalAtPositionAnyDirection( const Asura_Vector_3& xPosition, Asura_Vector_3& xSurfaceNormal, u_int uLOSFlags = AsuraPolygonFlag_NoCollisions );



private:
	static ToolsAVP_Mode_Waypointing* s_pxThis;
	static Asura_Vector_2  s_xAVPOverlayPosition;
    static bool            s_bShowEnvHooks;
    static bool            s_bShowEnvHooksChanged;
	static bool            s_bShowGS2Objects;
	static bool            s_bShowGS2ObjectsChanged;
	static int			   s_iShowDataType;
    static bool            s_bOnlyShowForwardFacingData;
    static bool            s_bRenderColoursAsFWC;
    static bool            s_bShowFailedLinkRoutes;
    static u_int           s_uFailedLinkRouteIndex;
    static bool            s_bFailedLinkRouteIndexChanged;
    static u_int           s_uFailedLinkPositionIndex;
    static float           s_fFLPIKeyDownTimer;
    static float           s_fFLPIKeyRepeatTimer;
    static Asura_Vector_3* s_pxPhysicsVelocities;
    static Asura_Quat*     s_pxPhysicsOrientations;
	static int			   s_iMinIslandSize;
    static Asura_Bounding_Box s_xPhysicsBoundingBox;
	static bool			   s_bIncludeLoFData;
	static bool			   s_bShowGamePlayVolumes;
    enum { MAX_FAILED_LINK_ROUTES = 400 };
    struct LinkRouteData
    {
        LinkRouteData()
		: m_xStartPosition( Asura_Maths::ZeroVector3 )
		, m_xFinishPosition( Asura_Maths::ZeroVector3 )
        , m_xBB()
        , m_uEntryCount( 0 )
        , m_pxVelocityArray( NULL )
        , m_pxPositionArray( NULL )
        , m_pxOrientationArray( NULL )
        {
        }
        bool InitialiseArrays( const u_int uPositionCount )
        {
            ShutdownArrays();
            m_uEntryCount        = uPositionCount;
            m_pxVelocityArray    = new Asura_Vector_3[ m_uEntryCount ];
            m_pxPositionArray    = new Asura_Vector_3[ m_uEntryCount ];
            m_pxOrientationArray = new Asura_Quat[ m_uEntryCount ];
            return ( m_pxVelocityArray && m_pxPositionArray && m_pxOrientationArray );
        }
        void ShutdownArrays()
        {
            delete [] m_pxVelocityArray;
            m_pxVelocityArray = NULL;
            delete [] m_pxPositionArray;
            m_pxPositionArray = NULL;
            delete [] m_pxOrientationArray;
            m_pxOrientationArray = NULL;
        }

		Asura_Vector_3     m_xStartPosition;
		Asura_Vector_3     m_xFinishPosition;
        Asura_Bounding_Box m_xBB;
        u_int              m_uEntryCount;
        Asura_Vector_3*    m_pxVelocityArray;
        Asura_Vector_3*    m_pxPositionArray;
        Asura_Quat*        m_pxOrientationArray;
    };
	
    static Asura_String  s_xNumFailedLinkRoutesString;
    static u_int         s_uNumFailedLinkRoutes;
    static LinkRouteData s_axFailedLinkRoutes[ MAX_FAILED_LINK_ROUTES ];

	static float s_fAttractorAngleTolerance;
    static float s_fWaypointVolumeMinAngle;
    static float s_fWaypointVolumeMaxAngle;
    static float s_fLinkMaxAngle;
    static float s_fTransitionLinkMinAngle;
    static float s_fTransitionLinkMaxAngleToPerfect;
    static float s_fSurfaceAngleTolerance;
    static float s_fMinTransitionLinkDistance;
    static float s_fIdealTransitionLinkDistance;
    static float s_fMaxTransitionLinkDistance;
    static float s_fDistanceAngleScoreWeighting;
    static float s_fTransitionLinkMinAcceptableScore;

    static float s_fMinFloorCeilingJumpDistance;
    static float s_fMaxFloorCeilingJumpDistance;
    static float s_fMinCeilingFloorFallDistance;
    static float s_fMaxCeilingFloorFallDistance;
    static float s_fMinWallWallJumpDistance;
    static float s_fMaxWallWallJumpDistance;
    static float s_fJumpTargetSurfaceAngleTolerance;

    static float                        s_fMinAlienWaypointRadius;
    static Asura_Physics_Object*        s_pxHumanoidPhysicsObject;
	static Asura_Collision_Box			s_xAlienTestCollisionBox;
    static Asura_Collision_Box          s_xHumanoidTestCollisionBox;
    static AVP_Tools_Waypoint_Searcher* s_pxWaypointSearcher;

	static bool s_bOutlineModulePolyIndex;
	static u_int s_uOutlineModuleIndex;
	static u_int s_uOutlinePolyIndex;

    enum AVP_TAB_NAMES
    {
        AVP_TAB_SETTINGS,
        AVP_TAB_RENDERING,
        AVP_TAB_DEBUGGING,
        AVP_TAB_NUM_TAB_NAMES
    };
    static const char* s_aszAVPTabNames[ AVP_TAB_NUM_TAB_NAMES ];

	enum ShowDataType
	{
		SDT_ALIEN,
		SDT_PREDATOR,
		SDT_HUMANOID,
		SDT_ALL,
		SDT_END_ENUM
	};
	static const char* s_aszAVPSDTNames[ SDT_END_ENUM ];

	struct Gs2WayPointID // used to identify way points - since no information is available position/ normal is used
	{
		Asura_Vector_3 m_xPosition;
		Asura_Vector_3 m_xNormal;
	};

	static Asura_LinkList< Gs2WayPointID > s_xAlienInVentGS2;
	static Asura_LinkList< Gs2WayPointID > s_xAlienOutVentGS2;

    enum { CURRENT_MODE_DATA_VERSION = 2 };
};

#endif   // ifndef __TOOLSAVP_MODE_WAYPOINTING_H__

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