#include "MW4Headers.hpp"
#include "Adept\AdeptHeaders.hpp"

#include "mw4.hpp"
#include "moverai.hpp"
#include "Adept\Interface.hpp"
#include "Adept\Application.hpp"
#include "Adept\player.hpp"
#include "torso.hpp"

#include "aimovedata.hpp"

using namespace MechWarrior4;
using namespace MW4AI;
#pragma warning (push)
#include <algorithm>
#pragma warning (pop)

const Stuff::Scalar min_twist_speed = 0.15f;
const Stuff::Scalar max_twist_speed = 0.40f;

CLookoutData::CLookoutData (MW4AI::CRailGraph *graph,MoverAI *owner) : CMoveData (graph,owner)
{
	m_LookDir = true;
	m_MoveType = MOVE_LOOKOUT;
}

void CLookoutData::Save (MemoryStream *stream)
{
	*stream << m_LookDir;
	*stream << m_LastLookSpeed;
	*stream << m_Slowing;

	CMoveData::Save (stream);
}

void CLookoutData::Load (MemoryStream *stream)
{
	*stream >> m_LookDir;
	*stream >> m_LastLookSpeed;
	*stream >> m_Slowing;
	CMoveData::Load (stream);
}

void CLookoutData::StartExecuting (MoverAI *ai,Stuff::Time till)
{
	inherited::StartExecuting (ai,till);
	m_LastLookSpeed = 0;
	m_LookDir = (bool)(ai->vehicle->objectID & 0x01);
	m_Slowing = false;
	m_MoveType = MOVE_LOOKOUT;
}

void CLookoutData::Execute (MoverAI *ai,Stuff::Time till)
{
	const Scalar accel = 0.10f;

	inherited::Execute (ai,till);
	CommandEntry *com;
	const Torso__GameModel *torsomodel=NULL;
	if (ai->m_MWObject)
		if (ai->m_MWObject->GetTorso())
			torsomodel = static_cast<const Torso__GameModel *> (ai->m_MWObject->GetTorso ()->GetGameModel ()) ;
		else
			return;


	if (!torsomodel)
		return;

	Verify (ai->m_MWObject);
	Verify(torsomodel);
	Scalar temp;

	Scalar twist_speed(min_twist_speed + (Stuff::Random::GetFraction() * (max_twist_speed - min_twist_speed)));

	if (twist_speed > torsomodel->twistSpeed)
	{
		twist_speed = torsomodel->twistSpeed;
	}

	Scalar dist,slowtime,slowdist;
	Scalar maxrad;
	maxrad = torsomodel->twistRadius;
	Max_Clamp (maxrad,1.5f);		// ~90 degrees
	if (m_LookDir)
		dist = maxrad - ai->m_MWObject->GetTorso ()->yawValue;
	else
		dist = (-maxrad) - ai->m_MWObject->GetTorso ()->yawValue;
	if (dist < 0.0f)
		dist *= -1.0f;

	slowtime = (0.1f * twist_speed) / (accel*twist_speed);
	slowdist = (0.5f * -(accel*twist_speed) * (slowtime*slowtime)) + (m_LastLookSpeed*twist_speed*slowtime);
	if (dist <= slowdist)
		m_Slowing = true;
	temp = accel;
	if ((dist < (accel * 3.0f)) || (m_Slowing && (m_LastLookSpeed == 0)))
	{
		m_LookDir = !m_LookDir;
		m_LastLookSpeed = 0;
		m_Slowing = false;
	}

	Stuff::Scalar amount;
	if (m_Slowing)
		m_LastLookSpeed -= temp;
	else
		m_LastLookSpeed += temp;
	if (m_LastLookSpeed < 0)
		m_LastLookSpeed = 0;
	else if (m_LastLookSpeed > 1.0f)
		m_LastLookSpeed = 1.0f;

	if (m_LookDir)
		amount = m_LastLookSpeed;
	else
		amount = -m_LastLookSpeed;

	Clamp(amount,-0.3f,0.3f);
	com = ai->CreateTrackToCommand (amount);
	Check_Pointer (com);
	ai->ExecuteCommand (com);
}

