#include "PlatformPrecomp.h"
#include "FPSControlComponent.h"
#include "util/GLESUtils.h"
#include "Entity/EntityUtils.h"
#include "BaseApp.h"
#include "GUI/GameMenu.h"

#define C_GUI_FADE_OUT_TIMER 400
#define C_GUI_FADE_IN_TIMER 150


FPSControlComponent::FPSControlComponent()
{
	SetName("FPSControl");
}

FPSControlComponent::~FPSControlComponent()
{
}

void FPSControlComponent::OnAdd(Entity *pEnt)
{
	EntityComponent::OnAdd(pEnt);
	m_pArrowEnt = NULL;
	m_pCenterBall = NULL;
	m_pPos2d = &GetParent()->GetVar("pos2d")->GetVector2();
	m_lastTouchDir = CL_Vec2f(0, 0); //the middle
	
	m_bTouchingArrows = false;
	

	//register ourselves to render if the parent does
	GetParent()->GetFunction("OnRender")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnRender, this, _1));
	GetParent()->GetFunction("OnUpdate")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnUpdate, this, _1));
	
	float guiTrans = GetApp()->GetVar("gui_transparency")->GetFloat();
	GetApp()->GetVar("gui_transparency")->Set(guiTrans);

	GetBaseApp()->m_sig_arcade_input.connect(1, boost::bind(&FPSControlComponent::OnArcadeInput, this, _1));	

	m_arrowMinTransparency = guiTrans;
	m_arrowMaxTransparency = rt_max(0.5f, guiTrans);

	//movement arrows?

	if (GetApp()->GetUsingTouchScreen())
	{

		m_pArrowEnt = CreateOverlayEntity(GetParent(), "arrow_gui", ReplaceWithDeviceNameInFileName("interface/iphone/arrows.rttex"), 0, 0);
	
		EntityComponent *pStripComp = m_pArrowEnt->AddComponent(new TouchStripComponent);
		m_pArrowEnt->GetVarWithDefault(string("touchPadding"), Variant(CL_Rectf(100, 100, 100, 100)))->GetRect();
		//m_pArrowEnt->AddComponent(new TouchHandlerComponent);
		
		//for speed, we've disabled movement message handling in App.cpp, but we actually want them just here, so we'll hardwire it
		AddInputMovementFocusIfNeeded(m_pArrowEnt);

		m_pArrowEnt->GetFunction("OnTouchStripUpdate")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnStripUpdate, this, _1));	
		m_pArrowEnt->GetFunction("OnOverStart")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnOverStart, this, _1));	
		m_pArrowEnt->GetFunction("OnOverEnd")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnOverEnd, this, _1));	
		
		GetParent()->GetParent()->GetFunction("OnKillingControls")->sig_function.connect(1, boost::bind(&FPSControlComponent::OnKillingControls, this, _1));	
		SetAlphaEntity(m_pArrowEnt, 0);
		FadeEntity(m_pArrowEnt, true, m_arrowMinTransparency, 300, 0);
	
		//limit it to touches only on the left side of the screen

		//m_pCenterBall = CreateOverlayEntity(m_pArrowEnt, "center_ball", "interface/center_ball.rttex",0,0);
		
		if (m_pCenterBall)
		{
			m_pCenterBall->GetVar("color")->Set(MAKE_RGBA(255,255,255,0));
			//SetAlphaEntity(m_pCenterBall, 0);
			SetAlignmentEntity(m_pCenterBall, ALIGNMENT_CENTER);
		}

		m_timeOfLastTouch = GetTick(TIMER_SYSTEM);
		SetAlignmentEntity(m_pArrowEnt, ALIGNMENT_CENTER);
		
		CL_Vec2f vArrowPos = FlipXIfNeeded(iPhoneMap(CL_Vec2f(80, 240)));
		if (IsIPAD())
		{
			if (IsInFlingMode())
			{
				vArrowPos = CL_Vec2f( FlipXIfNeeded(149-30), C_FLING_JOYSTICK_Y);
			} else
			{
				vArrowPos = FlipXIfNeeded(CL_Vec2f(137-20, 651-80));
			}
		}
		
		m_pArrowEnt->GetVar("pos2d")->Set(vArrowPos);
		m_vArrowImageSizeOver2 = m_pArrowEnt->GetVar("size2d")->GetVector2()/2;
	
        VariantList vList;
		OnOverEnd(&vList);
	}
	
}

void FPSControlComponent::OnRemove()
{
	EntityComponent::OnRemove();
}

void SendKey(eDinkInput key, bool bIsDown)
{
	if (bIsDown)
	{
		g_dglo.m_dirInput[key] = true;
		g_dglo.m_dirInputFinished[key] = false; //make sure it wasn't scheduled to stop pressing
	} else
	{
		g_dglo.m_dirInputFinished[key] = true;
	}
}

void FPSControlComponent::ProcessLastJoystickReading()
{
	CL_Vec2f vDir = m_lastTouchDir;
	vDir.normalize();

	if (m_pCenterBall)
	m_pCenterBall->GetVar("pos2d")->Set(m_vArrowImageSizeOver2+vDir* (rt_min(m_lastTouchDir.length(), 1) * 58));
		
	float deadSpace = 0.25f/2;
	
	if (IsInFlingMode())
	{
		deadSpace *= 1.4f;
	} else
	{
		if (IsIPADSize) deadSpace *= 2;

	}

	if (m_lastTouchDir.length() < deadSpace)
	{
		//dead space
		if (m_pCenterBall)
		{
			m_pCenterBall->GetVar("pos2d")->Set(m_vArrowImageSizeOver2);
		}
		return;
	}

	//convert to 360 degrees
	int dir = (int(RAD2DEG(atan2(m_lastTouchDir.y, m_lastTouchDir.x))+(90)));

	const int maxDirections = 8;
	int finaldir = mod(dir+ (360/ (maxDirections*2)), 360)/ (360/maxDirections);

	//nah, let's do 8 actually

	//LogMsg("Pressing %s, which is dir %d (final: %d)", PrintVector2(m_lastTouchDir).c_str(), dir, finaldir);

	switch (finaldir)
	{
	case 0:  SendKey(DINK_INPUT_UP, true); break;
	case 1:  SendKey(DINK_INPUT_RIGHT, true); SendKey(DINK_INPUT_UP, true); break;

	case 2:  SendKey(DINK_INPUT_RIGHT, true); break;
	case 3:  SendKey(DINK_INPUT_RIGHT, true); SendKey(DINK_INPUT_DOWN, true);  break;
	case 4:  SendKey(DINK_INPUT_DOWN, true);  break;

	case 5:  SendKey(DINK_INPUT_DOWN, true);  SendKey(DINK_INPUT_LEFT, true);  break;
	case 6:  SendKey(DINK_INPUT_LEFT, true);  break;
	case 7:  SendKey(DINK_INPUT_LEFT, true);  SendKey(DINK_INPUT_UP, true);  break;
	}
}
void FPSControlComponent::OnKillingControls(VariantList *pVList)
{
	RemoveFocusIfNeeded(m_pArrowEnt);
	
}

void FPSControlComponent::OnArcadeInput(VariantList *pVList)
{
	int vKey = pVList->Get(0).GetUINT32();
	bool bIsDown = pVList->Get(1).GetUINT32() != 0;

	//LogMsg("Key %d, down is %d", vKey, int(bIsDown));
	switch (vKey)
	{
	case VIRTUAL_KEY_DIR_LEFT:
		SendKey(DINK_INPUT_LEFT, bIsDown);
		break;

	case VIRTUAL_KEY_DIR_RIGHT:
		SendKey(DINK_INPUT_RIGHT, bIsDown);
		break;

	case VIRTUAL_KEY_DIR_UP:
		SendKey(DINK_INPUT_UP, bIsDown);
		break;

	case VIRTUAL_KEY_DIR_DOWN:
		SendKey(DINK_INPUT_DOWN, bIsDown);
		break;
	}
}


void FPSControlComponent::OnOverStart(VariantList *pVList)
{
}

void FPSControlComponent::OnOverEnd(VariantList *pVList)
{
	m_bTouchingArrows = false;
	ClearKeyInput();
	if (m_pCenterBall)
	m_pCenterBall->GetVar("color")->Set(MAKE_RGBA(255,255,255,0));

	//m_pArrowEnt->GetVar("alpha")->Set(1.0f);
	FadeEntity(m_pArrowEnt, false, m_arrowMinTransparency, C_GUI_FADE_OUT_TIMER);
	if (m_pCenterBall)
	FadeEntity(m_pCenterBall, false, 0.0, C_GUI_FADE_OUT_TIMER/3);
}

void FPSControlComponent::ClearKeyInput()
{
	SendKey(DINK_INPUT_UP, false);
	SendKey(DINK_INPUT_DOWN, false);
	SendKey(DINK_INPUT_LEFT, false);
	SendKey(DINK_INPUT_RIGHT, false);
}

void FPSControlComponent::ProcessArrowInput(CL_Vec2f vDir)
{
	if (m_bTouchingArrows || 1)
	{
		m_lastTouchDir = vDir*2 - CL_Vec2f(1, 1);

		//update current position
		ClearKeyInput();
		ProcessLastJoystickReading();
	} else
	{
		//	m_lastTouchDir = CL_Vec2f(0,0);
		if (m_pCenterBall)
			m_pCenterBall->GetVar("pos2d")->Set(m_lastTouchDir);
	}
}

void FPSControlComponent::OnStripUpdate(VariantList *pVList)
{
	if (!m_bTouchingArrows)
	{
		m_bTouchingArrows = true;
		//m_pArrowEnt->GetVar("pos2d")->Set( ConvertEntityClickToScreenCoords(pVList->Get(0).GetVector2(), pVList->Get(1).GetEntity()));
		//ProcessArrowInput(pVList->Get(1).GetVector2());
		if (m_pCenterBall)
			m_pCenterBall->GetVar("color")->Set(MAKE_RGBA(255,255,255,255));

		FadeEntity(m_pArrowEnt, false, m_arrowMaxTransparency, C_GUI_FADE_IN_TIMER);
		if (m_pCenterBall)
		FadeEntity(m_pCenterBall, false, m_arrowMaxTransparency, C_GUI_FADE_OUT_TIMER/3);

	}
	ProcessArrowInput(pVList->Get(1).GetVector2());
}

void FPSControlComponent::OnRender(VariantList *pVList)
{
	CL_Vec2f vFinalPos = pVList->m_variant[0].GetVector2()+*m_pPos2d;
}

void FPSControlComponent::OnUpdate(VariantList *pVList)
{
}