// This file is part of ThriceBall.
//
// Author: Kai Hillenbrand (AnTeevY)
// © Copyright, 2009 by Kai Hillenbrand, http://www.anteevy.de

// --------------------------------------------------

#include "checkpoint.h"

CCheckpoint::CCheckpoint(CRenderer *renderer, CLevel *level, NxOgre::Scene *scene, OGRE3DRenderSystem *rendersys)
	: m_pRenderer(renderer), m_pLevel(level), m_pScene(scene), m_pRenderSystem(rendersys), m_iType(0),
	m_fXPos(0), m_fYPos(0), m_fZPos(0)
{
	m_pSceneMgr = m_pRenderer->getSceneManager();
	m_pPlayer = m_pRenderer->getPlayer();
}

void CCheckpoint::create(float x, float y, float z, int type)
{
	// apply the variables
	m_iType = type;
	m_fXPos = x;
	m_fYPos = y;
	m_fZPos = z;	

	// load the .nxs file
	NxOgre::ResourceSystem::getSingleton()->openArchive("models", "file:media/models");
	NxOgre::ArchiveResourceIdentifier nxs("models:checkpoint.nxs");
	NxOgre::Mesh* triangleMesh = NxOgre::MeshManager::getSingleton()->load(nxs);
	NxOgre::TriangleGeometry* triangleGeometry = new NxOgre::TriangleGeometry(triangleMesh);
	m_pScene->createSceneGeometry(triangleGeometry, NxOgre::Matrix44(NxOgre::Real3(m_fXPos, m_fYPos, m_fZPos)));
	
	// avoid twice the same entity name
	String entName = "";
	bool entExists = true;

	while (entExists)
	{
		entName = "Checkpoint_" + StringConverter::toString(Ogre::Math::RangeRandom(0,10000));
		entExists = m_pSceneMgr->hasEntity(entName);
	}	

	// create the visible mesh
	Ogre::Entity* triangleEntity = m_pSceneMgr->createEntity(entName, "checkpoint.mesh");
	triangleEntity->setCastShadows(m_pRenderer->shadowsEnabled());
	Ogre::SceneNode* triangleNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	triangleNode->attachObject(triangleEntity);
	triangleNode->setPosition(Vector3(m_fXPos, m_fYPos, m_fZPos));

	setupVolume();	// sets up volume and trigger
}

void CCheckpoint::setupVolume()
{
	m_pVolume = m_pScene->createVolume(new NxOgre::Box(2), 
		NxOgre::Matrix44(NxOgre::Real3(m_fXPos, m_fYPos, m_fZPos)),	this, NxOgre::Enums::VolumeCollisionType_EnterOrExit);
}

void CCheckpoint::onVolumeEvent(NxOgre::Volume* volume, NxOgre::Shape* volumeShape, NxOgre::RigidBody* rigidBody, 
		NxOgre::Shape* rigidBodyShape, unsigned int collisionEvent)
{
	NxOgre::Actor* actor = static_cast<NxOgre::Actor*>(rigidBody);

	if ((volume == m_pVolume) && (actor == m_pPlayer->getCurBall()))
	{
		// if ball enters the volume, this is the new checkpoint and respawn point
		if (collisionEvent == NxOgre::Enums::VolumeCollisionType_OnEnter)
		{
			m_pLevel->setCurCheckpoint(this);	// inform the level that this is the current checkpoint
			m_pPlayer->setRespawnPos(NxOgre::Vec3(m_fXPos, m_fYPos + 1,m_fZPos), m_iType);
			m_pPlayer->canChangeType(true);	// player can now change the ball's type

			// if it's a finish checkpoint, won game
			if (m_iType == 1)
			{
				m_pPlayer->gameWin();
			}
		}
		else if(collisionEvent == NxOgre::Enums::VolumeCollisionType_OnExit)
		{
			// if ball leaves the volume, the player can no longer change its type
			m_pPlayer->canChangeType(false);
		}
	}
}
