//===========================================================================//
// File:	MW4EdApplication.cpp											 //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/02/97  DPB  Infrastructure changes.                                    //
// 11/03/98  SMJ  MW4 changes.												 //
//---------------------------------------------------------------------------//
// Copyright (C) 1995-97, Virtual World Entertainment, Inc.                  //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "stdafx.h"
#include "MW4GameEd.h"
#include "MW4GameEdApplication.hpp"
#include <MW4\MWApplication.hpp>
#include <Adept\Map.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <MW4\VehicleInterface.hpp>
#include <Adept\Player.hpp>
#include "MainFrm.h"
#include <MW4\Rail_move.hpp>
#include <mw4\mwmission.hpp>
#include <Adept\DropZone.hpp>
#include <Adept\EntityManager.hpp>
#include <io.h>
#include <Adept\Mission.hpp>
#include "DisplayWindow.h"
#include "OverviewWindow.h"
#include "InstanceWindow.h"
#include <MW4\MWTool.hpp>
#include <BuildNum\BuildNum.h>
#include <Adept\ResourceEffectLibrary.hpp>
#include <MW4\MWPlayer.hpp>

#define __mbschr(s,c) (char*)_mbschr((const unsigned char*)(s),(c))
#define __mbsrchr(s,c) (char*)_mbsrchr((const unsigned char*)(s),(c))

extern CMW4GameEdApp theApp;
using namespace MW4AI;

//#############################################################################
//########################     MW4GameEdApplication      ######################
//#############################################################################

//#############################################################################
// Message Support
//
const Receiver::MessageEntry
	MW4GameEdApplication::MessageEntries[]=
{
	MESSAGE_ENTRY(MW4GameEdApplication, PauseGame)
};

MW4GameEdApplication::ClassData*
	MW4GameEdApplication::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MW4GameEdApplication::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MW4GameEdApplicationClassID,
			"MW4GameEdApplication",
			MWApplication::DefaultData,
			ELEMENTS(MessageEntries),
			MessageEntries
		);
	Check_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MW4GameEdApplication::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MW4GameEdApplication*
	MW4GameEdApplication::Make()
{
	return new MW4GameEdApplication;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MW4GameEdApplication::MW4GameEdApplication():
	MWApplication(DefaultData,false)
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MW4GameEdApplication::~MW4GameEdApplication()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MW4GameEdApplication::LoadGameMessageHandler(int connection, Stuff::MemoryStream *message)
{
	Check_Object(this);
	
	theApp.m_NumObjectives = 0;

	MWApplication::LoadGameMessageHandler(connection, message);

	theApp.overviewWindow->LoadImageFromMissionInstance(theApp.missionFileName);

	BYTE r, c;
	Scalar rowcell, colcell, offset = 0;

	Check_Object(Map::Instance);
	Map::Instance->GetElement()->GetSize(&r, &c);
	Map::Instance->GetElement()->GetDimensions(&offset,&offset,&rowcell,&colcell);
	theApp.displayWindow->mapX = c * colcell;
	theApp.displayWindow->mapZ = r * rowcell;
	theApp.overviewWindow->mapWidth = int(theApp.displayWindow->mapX);
	theApp.overviewWindow->mapHeight = int(theApp.displayWindow->mapZ);

	//
	//-------------------------------------------------------
	//We need to create a drop zone with the name PlayerStart
	//-------------------------------------------------------
	//
	if(NameTable::Instance->FindID("PlayerStart") == NameTable::NullObjectID)
	{
		Resource model_resource;
		SPEW(("scottjan","Get rid of the hard coded data file"));
		NotationFile dropzone_file("Content\\Misc\\DropZone.data");
		Tool::Instance->ConstructDataList(&model_resource, &dropzone_file);
		Check_Object(&model_resource);
		Verify(model_resource.DoesResourceExist());

		Entity::ClassID class_ID;
		class_ID = Entity::GetClassIDFromDataListID(model_resource.GetResourceID());
		Verify(class_ID != NullClassID);

		LinearMatrix4D	matrix = LinearMatrix4D::Identity;
//		Point3D translation(500.0, 0.0, 500.0);
		Scalar f;
		f =  -45.0f;
		Point3D translation(f, 0.0, f);
		matrix.BuildTranslation(translation);

		Adept::DropZone::CreateMessage drop_zone_message(
			 sizeof(Adept::DropZone::CreateMessage),
			 DefaultEventPriority,
			 Adept::DropZone::CreateMessage::DefaultFlags,
			 class_ID,
			 Adept::DropZone::DefaultFlags,
			 model_resource.GetResourceID(),
			 matrix,
			 0.0f,
			 Entity__ExecutionStateEngine::NeverExecuteState,
			 NameTable::NullObjectID,
			 Entity::DefaultAlignment,
			 ResourceID::Null
		);

		MemoryStream stream(&drop_zone_message, drop_zone_message.messageLength);

		ReplicatorID Path_id = Connection::Local->GetNextReplicatorID();
		Entity* entity;
		entity = Entity::CreateEntity(&stream, &Path_id, false);
		Check_Object(entity);
		Verify(entity->IsDerivedFrom(DropZone::DefaultData));

		//Check_Object(EntityManager::Instance);
		//EntityManager::Instance->GetNameSocket()->Remove(entity);
		entity->instanceName = "PlayerStart";
		//EntityManager::Instance->GetNameSocket()->AddValue(entity, entity->instanceName);
		Check_Object(Map::Instance);
		Map::Instance->AddChild(entity);

		entity->SetPropType(Entity::MissionPropType);
		entity->SyncMatrices(true);

		Verify(entity->IsDerivedFrom(DropZone::DefaultData));
		 NameTable::Instance->AddEntry(entity, NameTable::DropZoneArray);
		NameTable::Instance->IsValid();
//		EntityManager::Instance->RequestPostCollisionExecution(entity);
		Map::Instance->UpdateZone(entity);
	}
	theApp.m_MissionSaved = true;
	MWMission *mission = Cast_Object (MWMission *,Mission::Instance);
	theApp.m_ScriptName = mission->scriptName;

	theApp.ambientLightIndex = -1;
	theApp.keyLightIndex = -1;
	theApp.fillLightIndex = -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MW4GameEdApplication::EnterRunningGameState(void* data)
{
	Check_Object(this);
	

	MWApplication::EnterRunningGameState(data);

//	CMenu* m = theApp.m_pMainWnd->GetMenu();
//	m->EnableMenuItem(3,MF_ENABLED | MF_BYPOSITION);
	theApp.m_pMainWnd->DrawMenuBar();
	theApp.toolBar->EnableButton(ID_FILE_SAVE);

	theApp.m_editorState = CMW4GameEdApp::SelectingObjectState;

	if (!MW4AI::g_MissionGraph)
	{
		MW4AI::g_MissionGraph = new CRailGraph(CRailGraph::DefaultData);

//		write RailGraph=xGraph.data in mission.instance
//		CreateMissionResource(missionname);
	}

	theApp.LoadLattice();

	theApp.m_showLattice = true;
	theApp.OnToolsMovementlattice(); // this will set m_showLattice to false

	theApp.m_showDropZones = true;
	theApp.OnToolsMovmentlayerShowdropzones();
	theApp.m_showAI = true;
	theApp.OnToolsMovmentlayerShowobjectives();

	theApp.m_CurPath = NULL;
	theApp.m_CurPathNodeCount = 0;

	//	Create editor iface objects for paths
	theApp.LoadPaths();
	theApp.LoadLights();
	theApp.LoadObjectives();
	theApp.LoadCameras();

	int i;
	Adept::Mission::Instance->GetMissionPolygon(theApp.missionBoundary);
	Adept::Mission::Instance->GetWarningPolygon(theApp.warningBoundary);

	for (i = 0; i < theApp.missionBoundary.GetLength(); i++)
	{
		theApp.missionBoundary[i].x /= Map::Instance->GetColumnZoneScale();
		theApp.missionBoundary[i].y /= Map::Instance->GetRowZoneScale();
		theApp.missionBoundary[i].x-=theApp.overviewWindow->mapWidth*0.5f;
		theApp.missionBoundary[i].y-=theApp.overviewWindow->mapHeight*0.5f;
	}

	for ( i = 0; i < theApp.warningBoundary.GetLength(); i++)
	{
		theApp.warningBoundary[i].x /= Map::Instance->GetColumnZoneScale();
		theApp.warningBoundary[i].y /= Map::Instance->GetRowZoneScale();
		theApp.warningBoundary[i].x-=theApp.overviewWindow->mapWidth*0.5f;
		theApp.warningBoundary[i].y-=theApp.overviewWindow->mapHeight*0.5f;
	}

	theApp.LoadBoundary();
	theApp.LoadDropZones();

	// Load any predefined camera positions

	_finddata_t filedata;
	char path[MAX_PATH],tmpString[MAX_PATH],*p;
	strcpy(tmpString,theApp.missionFileName);
	p = strrchr(tmpString,'.');
	*p = 0;
	sprintf(path,"%s.editcameras",tmpString);

	if (_findfirst(path,&filedata) == -1)	// no presets file
	{
		for (int i = 0; i < 10; i++)
    {
			theApp.m_DefCameraPos[i] = Stuff::LinearMatrix4D::Identity;
      theApp.m_DefCameraName[i][0] = (char)('0' + (char)i); 
      theApp.m_DefCameraName[i][1] = 0; 
    }
	}
	else
	{
		Stuff::Point3D trans;
		Stuff::YawPitchRoll rot;
		Stuff::LinearMatrix4D matrix = Stuff::LinearMatrix4D::Identity;
		
		NotationFile infile(path);

		for (int i = 0; i < 10; i++)
		{
			Page *page = infile.FindPage(itoa(i,tmpString,10));
			if (page)
			{
				page->GetEntry("Translation",&trans);
				page->GetEntry("YawPitchRoll",&rot);
        const char * ptr = NULL;
        page->GetEntry("CameraName", &(ptr), FALSE);
        if (ptr)
          lstrcpy(theApp.m_DefCameraName[i], ptr);
			}

			if (!page || (trans.x == 0.0f && trans.y == 0.0f && trans.z == 0.0f &&
				rot.yaw == 0.0f && rot.pitch == 0.0f && rot.roll == 0.0f))
			{
				theApp.m_DefCameraPos[i] = Stuff::LinearMatrix4D::Identity;
        theApp.m_DefCameraName[i][0] = (char)('0' + (char)i); 
        theApp.m_DefCameraName[i][1] = 0;
			}
			else
			{
				matrix.BuildTranslation(trans);
				matrix.BuildRotation(rot);

				theApp.m_DefCameraPos[i] = matrix;
			}
		}
    theApp.UpdateCameraMenus(-1);
	}

	MW4AI::g_MissionGraph->m_SaveLineElementMemory = true;
	VehicleInterface *temp_interface = 
		Cast_Object(VehicleInterface *, Player::Instance->playerInterface);

	temp_interface->cameraOffset = Point3D::Identity;

	LinearMatrix4D	new_local_to_parent = LinearMatrix4D::Identity;
	Point3D new_position = Point3D::Identity;
	YawPitchRoll new_rotation = YawPitchRoll::Identity;

	new_position.x = 0.0f;
	new_position.z = 0.0f;
	new_position.y = theApp.displayWindow->GetMapPointVertical(new_position.x,new_position.z) + theApp.cameraHeight;
	new_rotation.yaw = 0;
	new_local_to_parent.BuildTranslation(new_position);
	new_local_to_parent.BuildRotation(new_rotation);
	Player::Instance->SetNewLocalToParent(new_local_to_parent);
	Player::Instance->SyncMatrices(true);
	theApp.overviewWindow->UpdateCamera();
	theApp.overviewWindow->DrawWindow();

	theApp.OnToolsCameraheightMechheight10m();
	theApp.instanceWindow->ResetInstanceLists();
}

void
	MW4GameEdApplication::PauseGameMessageHandler(const PauseGameMessage *message)
{
	Check_Object(this);
	Check_Object(message);
	Verify(message->messageID == PauseGameMessageID);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


void
	MW4GameEdApplication::LoadMissionResources(const char *mission_name)
{

	//
	//---------------------------------------------------------
	// Get the mission instance name and the resource file name
	//---------------------------------------------------------
	//
	Stuff::MString mission_instance = mission_name;
	Stuff::MString res_name = "Resources\\";
	res_name += __mbschr(mission_instance,'\\')+1;
	char *p = __mbsrchr(res_name, '\\');
	Check_Pointer(p);
	Str_Copy(p, ".mw4", res_name.GetLength() - (p - res_name));

	//
	//-------------------------------------------------------------------
	// Open up the resource file as a database and access record 0.  This
	// will contain the list of resource files this one is dependant on
	//-------------------------------------------------------------------
	//
	Stuff::DatabaseHandle *database =
		new Stuff::DatabaseHandle(res_name, false, VER_CONTENTVERSION);
	Stuff::RecordHandle record;
	record.m_databaseHandle = database;
	record.m_ID = ResourceID::BuildDependenciesRecordID;
	#if defined(_ARMOR)
		bool result =
	#endif
	record.FindID();
	Verify(result);

	//
	//-------------------------
	// Load up the core effects
	//-------------------------
	//
	Verify(!gosFX::EffectLibrary::Instance);
	gosFX::EffectLibrary::Instance = new ResourceEffectLibrary;
	Resource core_libraries("{effects}");
	Verify(core_libraries.DoesResourceExist());
	ResourceID *lib = Cast_Pointer(ResourceID*, core_libraries.GetPointer());
	for (unsigned i=0; i<core_libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
	{
		Resource library(*lib);
		gosFX::EffectLibrary::Instance->Load(&library);
	}

	//
	//----------------------------------------------------------------------
	// The data points to a series of null terminated strings.  Step through
	// them until done
	//----------------------------------------------------------------------
	//
	const char* data = reinterpret_cast<const char*>(record.m_data);
	int level=MapResourceFileID;
	for (DWORD count=0; count<record.m_length; ++level)
	{
		if (!data[count])
			break;

		MString depstr=data+count;
		strcpy(strrchr(depstr,'.')+1,"dep");
		//
		//---------------------------
		// Load this resource file up
		//---------------------------
		//
		ResourceManager::Instance->OpenResourceFile(
			data+count,
			depstr,
			level,
			VER_CONTENTVERSION,
			true,
			false
		);

		//
		//----------------------------
		// Load up this file's effects
		//----------------------------
		//
		Resource libraries("{effects}");
		if (libraries.DoesResourceExist() && libraries.GetResourceID().GetFileID() == level)
		{
			ResourceID *lib = Cast_Pointer(ResourceID*, libraries.GetPointer());
			for (unsigned i=0; i<libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
			{
				Resource library(*lib);
				gosFX::EffectLibrary::Instance->Load(&library);
			}
		}
			
		count += strlen(data+count)+1;
	}

	//
	//---------------------------------
	// Now create our own resource file
	//---------------------------------
	//
	MString depstr=res_name;
	strcpy(strrchr(depstr,'.')+1,"dep");

	ResourceManager::Instance->OpenResourceFile(database, 
												depstr,
												level,
												VER_CONTENTVERSION, 
												true, 
												false);
	Resource libraries("{effects}");
	if (libraries.DoesResourceExist() && libraries.GetResourceID().GetFileID() == level)
	{
		ResourceID *lib = Cast_Pointer(ResourceID*, libraries.GetPointer());
		for (unsigned i=0; i<libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
		{
			Resource library(*lib);
			gosFX::EffectLibrary::Instance->Load(&library);
		}
	}
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

Entity::CreateMessage *
	MW4GameEdApplication::MakePlayerCreationMessage(int player_id)
{
	
	Resource vehicle_instance("Content\\Mechs\\ShadowCat\\shadowcat.instance");	
	MString interface_name = "Interfaces\\SimpleInterface\\SimpleInterface.instance";
	Resource interface_instance(interface_name);
	Resource player_data("Players\\TestPlayer\\TestPlayer.data");
	
	
	MWPlayer::CreateMessage *player_message =
		new MWPlayer::CreateMessage(
		sizeof(MWPlayer::CreateMessage),
		DefaultEventPriority,
		MWPlayer::CreateMessage::DefaultFlags,
		MWPlayerClassID,
		0,
		player_data.GetResourceID(),
		LinearMatrix4D::Identity,
		0.0f,
		MWPlayer::ExecutionStateEngine::AlwaysExecuteState,
		NameTableEntry::BuildObjectID(NameTable::PlayerArray, 0),
		Entity::Player,
		vehicle_instance.GetResourceID(),
		interface_instance.GetResourceID(),
		NameTable::NullObjectID,
		0,
		DefaultSkinPrefix,
		0,
		0
		);
	Check_Object(player_message);

	return player_message;

}
