#include "stdafx.h"
#include "MW4GameEd.h"
#include "SprayCommand.h"
#include "EditorWaypoint.h"
#include <Adept\Player.hpp>
#include <Adept\Entity.hpp>
#include <Adept\Interface.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Map.hpp>
#include "DisplayWindow.h"
#include "OverviewWindow.h"
#include "InstanceWindow.h"
#include "ResourceWindow.h"
#include "Transdlg.h"
#include "Selection.h"

extern CMW4GameEdApp theApp;

SprayCommand::SprayCommand(Entity *object)
	: Command()
{
	Check_Object(object);
	Check_Object(Map::Instance);

	if (object->IsDerivedFrom(EditorLatticeNode::DefaultData) || 
		object->IsDerivedFrom(EditorPathNode::DefaultData) || 
		object->IsDerivedFrom(EditorBoundaryNode::DefaultData))
	{
		STOP(("Illegal class passed into SprayCommand"));
	}

	CSelectionList::Instance->ClearSelectionList();

	moveOffset = Point3D::Identity;
	cursorPosition = object->GetLocalToWorld();

	Check_Pointer(theApp.instanceWindow);
		theApp.instanceWindow->ResetInstanceLists();
//	EntityManager::Instance->RequestPostCollisionExecution(object);
	Map::Instance->UpdateZone(object);

	CSelectionNode* command_node;
	Entity* sprayEntity[4];
	theApp.m_editorState = CMW4GameEdApp::WaitingToSprayState;
	sprayEntity[0] = theApp.resourceWindow->CreateNewInstance();

	LinearMatrix4D matrix = LinearMatrix4D::Identity;
	Point3D	point;

	point = object->GetLocalToParent();
	point.x += Stuff::Random::GetFraction() * 40 + 10;
	point.z += Stuff::Random::GetFraction() * 40 + 10;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z);

	matrix.BuildTranslation(point);
	sprayEntity[0]->SetNewLocalToParent(matrix);
	sprayEntity[0]->SyncMatrices(true);
	command_node = new CSelectionNode(sprayEntity[0]);
	Register_Object(command_node);
	selectedEntities.Add(command_node);
//	EntityManager::Instance->RequestPostCollisionExecution(sprayEntity[0]);
	Map::Instance->UpdateZone(sprayEntity[0]);
		theApp.instanceWindow->ResetInstanceLists();

	theApp.m_editorState = CMW4GameEdApp::WaitingToSprayState;
	sprayEntity[1] = theApp.resourceWindow->CreateNewInstance();

	matrix = LinearMatrix4D::Identity;
	point = object->GetLocalToParent();
	point.x -= Stuff::Random::GetFraction() * 40 + 10;
	point.z += Stuff::Random::GetFraction() * 40 + 10;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z);

	matrix.BuildTranslation(point);
	sprayEntity[1]->SetNewLocalToParent(matrix);
	sprayEntity[1]->SyncMatrices(true);
	command_node = new CSelectionNode(sprayEntity[1]);
	Register_Object(command_node);
	selectedEntities.Add(command_node);
//	EntityManager::Instance->RequestPostCollisionExecution(sprayEntity[1]);
	Map::Instance->UpdateZone(sprayEntity[1]);
		theApp.instanceWindow->ResetInstanceLists();

	theApp.m_editorState = CMW4GameEdApp::WaitingToSprayState;
	sprayEntity[2] = theApp.resourceWindow->CreateNewInstance();

	matrix = LinearMatrix4D::Identity;
	point = object->GetLocalToParent(); 25;
	point.z -= Stuff::Random::GetFraction() * 40 + 10;
	point.x -= Stuff::Random::GetFraction() * 40 + 10;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z);

	matrix.BuildTranslation(point);
	sprayEntity[2]->SetNewLocalToParent(matrix);
	sprayEntity[2]->SyncMatrices(true);
	command_node = new CSelectionNode(sprayEntity[2]);
	Register_Object(command_node);
	selectedEntities.Add(command_node);
//	EntityManager::Instance->RequestPostCollisionExecution(sprayEntity[2]);
	Map::Instance->UpdateZone(sprayEntity[2]);
		theApp.instanceWindow->ResetInstanceLists();

	theApp.m_editorState = CMW4GameEdApp::WaitingToSprayState;
	sprayEntity[3] = theApp.resourceWindow->CreateNewInstance();

	matrix = LinearMatrix4D::Identity;
	point = object->GetLocalToParent();
	point.x += Stuff::Random::GetFraction() * 40 + 10;
	point.z -= Stuff::Random::GetFraction() * 40 + 10;
	point.y = theApp.displayWindow->GetMapPointVertical(point.x,point.z);

	matrix.BuildTranslation(point);
	sprayEntity[3]->SetNewLocalToParent(matrix);
	sprayEntity[3]->SyncMatrices(true);
	command_node = new CSelectionNode(sprayEntity[3]);
	Register_Object(command_node);
	selectedEntities.Add(command_node);
//	EntityManager::Instance->RequestPostCollisionExecution(sprayEntity[3]);
	Map::Instance->UpdateZone(sprayEntity[3]);
		theApp.instanceWindow->ResetInstanceLists();

	CSelectionList::Instance->AddSelection(object);
	CSelectionList::Instance->AddSelection(sprayEntity[0]);
	CSelectionList::Instance->AddSelection(sprayEntity[1]);
	CSelectionList::Instance->AddSelection(sprayEntity[2]);
	CSelectionList::Instance->RemoveCollision();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SprayCommand::~SprayCommand()
{

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	SprayCommand::Execute()
{
	Move();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SprayCommand::Undo()
{
	Check_Pointer(theApp.instanceWindow);

	CSelectionNode *selection_node;

	if (!selectedEntities.IsEmpty())
	{
		ChainIteratorOf<CSelectionNode*> iterator(&selectedEntities);
		while((selection_node = iterator.ReadAndNext()) != NULL)
		{
			Check_Object(selection_node->selectedEntity);
			theApp.instanceWindow->RemoveInstance(selection_node->selectedEntity);
			theApp.displayWindow->translationDlg->CheckObject(selection_node->selectedEntity);
			selection_node->selectedEntity->SentenceToDeathRow();
		}
	}
	theApp.overviewWindow->DrawWindow();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	SprayCommand::Move()
{
	//This function needs to run through the list and move all according
	//to the offset of the cursor.  This is not going to be as easy as it
	//seems.  First just move one.

	Point3D  new_offset;
	LinearMatrix4D new_local_to_world;
	CSelectionNode *selection_node;
	Entity* entity;
	Point3D translation = Point3D::Identity;

	Check_Object(Player::Instance);
	Check_Object(Player::Instance->playerInterface);
	Entity *reticule;
	reticule = Player::Instance->playerInterface->reticuleEntity.GetCurrent();
	if(reticule)
	{
		Point3D world_offset = Player::Instance->playerInterface->reticuleOffset; 
		LinearMatrix4D new_local_to_parent = LinearMatrix4D::Identity;
		new_local_to_parent.Multiply(reticule->GetLocalToParent(), world_offset);
		translation = new_local_to_parent;
	}

	new_offset = translation;
	new_offset -= cursorPosition;
	if (!(selectedEntities.IsEmpty()))
	{
		ChainIteratorOf<CSelectionNode*> iterator(&selectedEntities);
		iterator.First();
		while((selection_node = iterator.ReadAndNext()) != NULL)
		{
			entity = selection_node->selectedEntity;
			Point3D target_in_world;
			target_in_world = entity->GetLocalToWorld();
			YawPitchRoll current_rotation;
			current_rotation = entity->GetLocalToParent();
			target_in_world += new_offset;
			moveOffset += new_offset;

			target_in_world.y = theApp.displayWindow->GetMapPointVertical(target_in_world.x,target_in_world.z);

			new_local_to_world.BuildTranslation(target_in_world);
			new_local_to_world.BuildRotation(current_rotation);

			Check_Object(entity);
			entity->SetNewLocalToParent(new_local_to_world);
			entity->SyncMatrices(true);

			Time till = gos_GetElapsedTime();
			entity->PostCollisionExecute(till);

			if (entity->GetCollisionMask() == Entity::EditorIsMovingFlag)
			{
				if (entity->IsMultiZone())
					entity->GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawRedBounds);
				else if (entity->IsMultiTile())
					entity->GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawYellowBounds);
				else
					entity->GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawGreenBounds);
			}
			else
				entity->GetElement()->SetCallbackIndex(ElementRenderer::Element::DrawGreenBounds);

		}
		cursorPosition = translation;
	}
}
