//////////////////////////////////////////////////////////////////////////////
//
// AVP_Profile_Controls.cpp
//
// (AJK - 25.07.2008) Created
//
// Copyright (c) 2008 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// core
#include "Core/Asura.h"

// header
#include "Core/Profile/AVP_Profile_Controls.h"

// Asura
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Interface/Asura_CommandConsole.h"

// AVP
#include "Core/AVP_Settings.h"
#include "GUIMenu/Asura_GUIMenu_System.h"

AVP_Profile_Controls::AVP_Profile_Controls()
{
	SetToDefaults();
}

void AVP_Profile_Controls::SetToDefaults()
{
	m_bInvertX			= false;
	m_bInvertY			= false;
	m_bVibrations		= true;
	m_bLeftHandControl	= false;
	m_bSimpleMovement	= false;
	m_bAutoCenter		= false;
	m_bAimAssist		= true;
	m_bLookAssist       = true;
	m_fXAxisSensitivity = 0.5f;
	m_fYAxisSensitivity = 0.5f;

	// the default setting for sensitivity is 0.5 the value of Log2Sensitivity should correspond to this.
	m_fLog2XAxisSensitivity = ApproxLog2( m_fXAxisSensitivity );
	m_fLog2YAxisSensitivity = ApproxLog2( m_fYAxisSensitivity );
}

void AVP_Profile_Controls::WriteToChunkStream(Asura_Chunk_Stream& xStream) 
{
	int iCurrentChunkVersion = CURRENT_CHUNK_VERSION;

	xStream << iCurrentChunkVersion;

	xStream << m_bInvertX;
	xStream << m_bInvertY;
	xStream << m_bVibrations;
	xStream << m_bLeftHandControl;
	xStream << m_bSimpleMovement;
	xStream << m_bAutoCenter;
	xStream << m_bAimAssist;
	xStream << m_bLookAssist;
	xStream << m_fXAxisSensitivity;
	xStream << m_fYAxisSensitivity;
}

void AVP_Profile_Controls::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	int iCurrentChunkVersion;

    xStream >> iCurrentChunkVersion;

	switch ( iCurrentChunkVersion )
	{
		case 1:
		{
			xStream >> m_bInvertX;
			xStream >> m_bInvertY;
			xStream >> m_bVibrations;
			xStream >> m_bLeftHandControl;
			xStream >> m_bSimpleMovement;
			xStream >> m_bAutoCenter;
			xStream >> m_bAimAssist;
			xStream >> m_bLookAssist;
			xStream >> m_fXAxisSensitivity;
			xStream >> m_fYAxisSensitivity;
			
			m_fLog2XAxisSensitivity = ApproxLog2( m_fXAxisSensitivity );
			m_fLog2YAxisSensitivity = ApproxLog2( m_fYAxisSensitivity );

			break;
		}
		case 0 :
		{
			xStream >> m_bAutoCenter;
			xStream >> m_bInvertY;
			xStream >> m_bAimAssist;
			xStream >> m_bLookAssist;
			xStream >> m_fXAxisSensitivity;
			xStream >> m_fYAxisSensitivity;
			m_fLog2XAxisSensitivity = ApproxLog2( m_fXAxisSensitivity );
			m_fLog2YAxisSensitivity = ApproxLog2( m_fYAxisSensitivity );
			break;
		}
		default :
		{
			Asura_Assertf(false, ("Unknown chunk version (%d) in AVP_Profile_Controls", iCurrentChunkVersion));
			break;
		}
	}
}

#if defined(ASURA_SUPPORT_COMMAND_CONSOLE)

void AVP_Profile_Controls::SetupConsoleCommands()
{
}

void AVP_Profile_Controls::SetupConsoleVariables()
{
	// Add the necessary console variables...
	Asura_CommandConsole::AddVar( L"ControlsMenu.InvertXAxis",		&m_bInvertX,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.InvertYAxis",		&m_bInvertY,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.Vibrations",		&m_bVibrations,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.LaftHandControl",	&m_bLeftHandControl,						Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.SimpleMovement",	&m_bSimpleMovement,							Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.AutoCenterCamera",	&m_bAutoCenter,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.Controls.AimAssist",		&m_bAimAssist,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.Controls.LookAssist",		&m_bLookAssist,								Asura_CommandConsole::REMOVE_AT_SHUTDOWN );

	Asura_CommandConsole::AddVar( L"ControlsMenu.XAxisSensitivity",	&m_fLog2XAxisSensitivity,	-2.0f, 2.0f,	Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"ControlsMenu.YAxisSensitivity",	&m_fLog2YAxisSensitivity,	-2.0f, 2.0f,	Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
}

void AVP_Profile_Controls::RemoveConsoleVariables()
{
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.InvertXAxis" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.InvertYAxis" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.Vibrations" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.LaftHandControl" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.SimpleMovement" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.AutoCenterCamera" );
	Asura_CommandConsole::RemoveVar( L"AVP.Controls.AimAssist" );
	Asura_CommandConsole::RemoveVar( L"AVP.Controls.LookAssist" );

	Asura_CommandConsole::RemoveVar( L"ControlsMenu.XAxisSensitivity" );
	Asura_CommandConsole::RemoveVar( L"ControlsMenu.YAxisSensitivity" );
}

#endif	// defined(ASURA_SUPPORT_COMMAND_CONSOLE)

void AVP_Profile_Controls::Update()
{
	if( Asura_GUIMenu_System::IsMenuPageHashActive( GetCurSpeciesControlsMenuHash() ) )
	{
		ApplySettings();
	}
}

void AVP_Profile_Controls::ApplySettings()
{
	m_fXAxisSensitivity = Asura_Maths::Power( 2, m_fLog2XAxisSensitivity );
	m_fYAxisSensitivity = Asura_Maths::Power( 2, m_fLog2YAxisSensitivity );
}

bool  AVP_Profile_Controls::operator!=(const AVP_Profile_Controls& xOther) const
{
	return 	 !(*this == xOther) ;
}

bool  AVP_Profile_Controls::operator==(const AVP_Profile_Controls& xOther) const
{
	return 	(m_bInvertX					== xOther.m_bInvertX				) &&
			(m_bInvertY			     == xOther.m_bInvertY             ) &&
			(m_bVibrations				== xOther.m_bVibrations				) &&
			(m_bLeftHandControl			== xOther.m_bLeftHandControl		) &&
			(m_bSimpleMovement			== xOther.m_bSimpleMovement			) &&
			(m_bAutoCenter				== xOther.m_bAutoCenter				) &&
	        (m_bAimAssist            == xOther.m_bAimAssist           ) &&	
			(m_bLookAssist           == xOther.m_bLookAssist          ) &&
			(m_fLog2XAxisSensitivity	== xOther.m_fLog2XAxisSensitivity	) &&
			(m_fLog2YAxisSensitivity	== xOther.m_fLog2YAxisSensitivity	);
}

u_int AVP_Profile_Controls::GetCurSpeciesControlsMenuHash()
{
	switch(AVP_Settings::GetPlayerSpecies())
	{
		case AVP_Settings::AVP_SPECIES_HUMAN :
		{
			return s_uAVP_PROFILE_MARINE_CONTROLS_MENU;
		}
		case AVP_Settings::AVP_SPECIES_ALIEN :
		{
			return s_uAVP_PROFILE_ALIEN_CONTROLS_MENU;
		}
		case AVP_Settings::AVP_SPECIES_PREDATOR :
		{
			return s_uAVP_PROFILE_PREDATOR_CONTROLS_MENU;
		}
		case AVP_Settings::AVP_SPECIES_UNKNOWN:
		{
			// This is valid, we don't know what species we are yet
			return ASURA_HASH_ID_UNSET; 
		}
		default :
		{
			Asura_Assert(false,"Wrong specie passed in AVP_Profile_Graphics");
			return ASURA_HASH_ID_UNSET;
		}
	}
}

float AVP_Profile_Controls::ApproxLog2( const float fX )
{
	const float fLog10_2 = 0.30102999566398119521373889472449f;
	const float fConst[5] =
	{
		0.868591718f,
		0.289335524f,
		0.177522071f,
		0.094376479f,
		0.191337714f
	};
	float fT		= ( fX - 1.0f ) / ( fX + 1.0f );
	float fTSq		= fT * fT;
	float fTemp		= fT;
	float fLog10_X	= 0.0f;
	for ( u_int uItr = 0; uItr < 5; ++uItr )
	{
		fLog10_X += fConst[ uItr ] * fTemp;
		fTemp *= fTSq;
	}
	return fLog10_X / fLog10_2;
}
