#include "MouseCursor.h"

#include <OgreTextureManager.h>
#include <OgreTechnique.h>

template<> MouseCursor* Ogre::Singleton<MouseCursor>::ms_Singleton = 0;

MouseCursor::MouseCursor(): guiOverlay(0), cursorContainer(0)
{
	material = Ogre::MaterialManager::getSingleton().create("MouseCursor/Default", "General");
	
	cursorContainer = (Ogre::OverlayContainer*) Ogre::OverlayManager::getSingletonPtr()->createOverlayElement("Panel", "MouseCursor");
	cursorContainer->setMaterialName(material->getName());
	cursorContainer->setPosition(0.0f, 0.0f);
	cursorContainer->hide();

	guiOverlay = Ogre::OverlayManager::getSingletonPtr()->create("MouseCursor");
	guiOverlay->setZOrder(649);
	guiOverlay->add2D(cursorContainer);
	guiOverlay->show(); 
}

MouseCursor::~MouseCursor()
{
	Ogre::OverlayManager::getSingletonPtr()->destroy(guiOverlay);
	Ogre::OverlayManager::getSingletonPtr()->destroyOverlayElement(cursorContainer);
	Ogre::MaterialManager::getSingleton().unload("MouseCursor/Default");
}

void MouseCursor::setImage(const Ogre::String& filename)
{
	texture = Ogre::TextureManager::getSingleton().load(filename, "General");
	Ogre::TextureUnitState *textureUnitState;

	if(material->getTechnique(0)->getPass(0)->getNumTextureUnitStates())
	{
		textureUnitState = material->getTechnique(0)->getPass(0)->getTextureUnitState(0);
	}
	else
	{
		textureUnitState = material->getTechnique(0)->getPass(0)->createTextureUnitState( texture->getName() );
	}

	textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
	material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
}

void MouseCursor::setWindowDimensions(unsigned int width, unsigned int height)
{
	windowWidth = (width > 0) ? width : 1;
	windowHeight = (height > 0) ? height : 1;

	cursorContainer->setWidth((double)texture->getWidth() / (double)windowWidth);
	cursorContainer->setHeight((double)texture->getHeight() / (double)windowHeight);
}

void MouseCursor::setVisible(bool visible)
{
	if(visible)
	{
		cursorContainer->show();
	}
	else
	{
		cursorContainer->hide();
	}
}

void MouseCursor::updatePosition(int x, int y)
{
	Ogre::Real rx = clamp(x / windowWidth, 0.0f, 1.0f);
	Ogre::Real ry = clamp(y / windowHeight, 0.0f, 1.0f);

	position.X = x;
	position.Y = y;
	position.normalisedX = rx;
	position.normalisedY = ry;

	cursorContainer->setPosition(rx, ry);
}

Ogre::Real MouseCursor::clamp(Ogre::Real a, Ogre::Real min, Ogre::Real max)
{
	if(a < min)
	{
		return min;
	}
	if(a > max)
	{
		return max;
	}

	return a;
}

MouseCursor* MouseCursor::getSingletonPtr(void)
{
    return ms_Singleton;
}

MouseCursor& MouseCursor::getSingleton(void)
{  
    assert(ms_Singleton);
	return (*ms_Singleton);
}