//--------------------------------------------------------------------------------------------------------
//========= Copyright Valve Corporation, All rights reserved. ============//

#include "cbase.h"

#include "SelectionTool.h"
#include "nav_mesh.h"
#include "nav_pathfind.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

#ifdef SERVER_USES_VGUI

using namespace vgui;


//--------------------------------------------------------------------------------------------------------
SelectionToolPanel::SelectionToolPanel( vgui::Panel *parent, const char *toolName ) : CNavUIToolPanel( parent, toolName )
{
	LoadControlSettings( "Resource/UI/NavTools/SelectionTool.res" );
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::Init( void )
{
	m_dragType = DRAG_NONE;
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::Shutdown( void )
{
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::PerformLayout( void )
{
	Panel *parent = GetParent();
	if ( parent )
	{
		int w, h;
		parent->GetSize( w, h );
		SetBounds( 0, 0, w, h );
	}

	BaseClass::PerformLayout();
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::OnCommand( const char *command )
{
	if ( FStrEq( "FloodSelect", command ) )
	{
		TheNavUI()->SetLeftClickAction( "Selection::Flood", "Flood Select" );
	}

	BaseClass::OnCommand( command );
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::OnCursorMoved( int x, int y )
{
	CNavArea *area = TheNavMesh->GetSelectedArea();
	if ( area )
	{
		bool selected = TheNavMesh->IsInSelectedSet( area );

		if ( selected && m_dragType == DRAG_UNSELECT )
		{
			TheNavMesh->RemoveFromSelectedSet( area );
			TheNavUI()->PlaySound( "EDIT_END_AREA.Creating" );
		}
		else if ( !selected && m_dragType == DRAG_SELECT )
		{
			TheNavMesh->AddToSelectedSet( area );
			TheNavUI()->PlaySound( "EDIT_END_AREA.Creating" );
		}
	}
	
	BaseClass::OnCursorMoved( x, y );
}


//--------------------------------------------------------------------------------------------------------
class FloodSelectionCollector
{
public:
	FloodSelectionCollector( SelectionToolPanel *panel )
	{
		m_count = 0;
		m_panel = panel;
	}

	bool operator() ( CNavArea *area )
	{
		// already selected areas terminate flood select
		if ( TheNavMesh->IsInSelectedSet( area ) )
			return false;

		if ( !m_panel->IsFloodSelectable( area ) )
			return false;

		TheNavMesh->AddToSelectedSet( area );
		++m_count;

		return true;
	}

	int m_count;

private:
	SelectionToolPanel *m_panel;
};


//--------------------------------------------------------------------------------------------------------
bool SelectionToolPanel::IsFloodSelectable( CNavArea *area )
{
	if ( IsCheckButtonChecked( "Place" ) )
	{
		if ( m_floodStartArea->GetPlace() != area->GetPlace() )
		{
			return false;
		}
	}

	if ( IsCheckButtonChecked( "Jump" ) )
	{
		if ( (m_floodStartArea->GetAttributes() & NAV_MESH_JUMP) != (area->GetAttributes() & NAV_MESH_JUMP) )
		{
			return false;
		}
	}

	return true;
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::FloodSelect( void )
{
	m_floodStartArea = TheNavMesh->GetSelectedArea();
	if ( m_floodStartArea )
	{
		TheNavUI()->PlaySound( "EDIT_DELETE" );

		int connections = INCLUDE_BLOCKED_AREAS;

		if ( IsCheckButtonChecked( "Incoming" ) )
		{
			connections = connections | INCLUDE_INCOMING_CONNECTIONS;
		}

		if ( !IsCheckButtonChecked( "Outgoing" ) )
		{
			connections = connections | EXCLUDE_OUTGOING_CONNECTIONS;
		}

		// collect all areas connected to this area
		FloodSelectionCollector collector( this );
		SearchSurroundingAreas( m_floodStartArea, m_floodStartArea->GetCenter(), collector, -1, connections );

		Msg( "Selected %d areas.\n", collector.m_count );
	}
	m_floodStartArea = NULL;

	TheNavMesh->SetMarkedArea( NULL );			// unmark the mark area
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::StartLeftClickAction( const char *actionName )
{
	if ( FStrEq( actionName, "Selection::Flood" ) )
	{
		TheNavUI()->SetLeftClickAction( "", "" );
		FloodSelect();
	}
	else if ( FStrEq( actionName, "Selection::Select" ) )
	{
		CNavArea *area = TheNavMesh->GetSelectedArea();
		if ( area )
		{
			if ( TheNavMesh->IsInSelectedSet( area ) )
			{
				TheNavMesh->RemoveFromSelectedSet( area );
				m_dragType = DRAG_UNSELECT;
			}
			else
			{
				TheNavMesh->AddToSelectedSet( area );
				m_dragType = DRAG_SELECT;
			}
			TheNavUI()->PlaySound( "EDIT_END_AREA.Creating" );
		}
	}
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::FinishLeftClickAction( const char *actionName )
{
	m_dragType = DRAG_NONE;
}


//--------------------------------------------------------------------------------------------------------
void SelectionToolPanel::StartRightClickAction( const char *actionName )
{
	if ( m_dragType != DRAG_NONE )
	{
		TheNavUI()->PlaySound( "EDIT_END_AREA.Creating" );
		m_dragType = DRAG_NONE;
		return;
	}

	if ( FStrEq( actionName, "Selection::ClearSelection" ) )
	{
		if ( FStrEq( TheNavUI()->GetLeftClickAction(), "Selection::Select" ) )
		{
			if ( TheNavMesh->GetSelecteSetSize() > 0 )
			{
				TheNavUI()->PlaySound( "EDIT_END_AREA.Creating" );
			}
			TheNavMesh->ClearSelectedSet();
		}
		else
		{
			TheNavUI()->SetLeftClickAction( "", "" );
		}
	}
}

#endif // SERVER_USES_VGUI


//--------------------------------------------------------------------------------------------------------