#include "MySdkTrays.h"
// Mingyu: my implementation of SdkTrayManager functions for external controls (wii remote and PPT)

#define MAX(x,y) (x) > (y) ? (x) : (y)
#define MIN(x,y) (x) < (y) ? (x) : (y)

namespace OgreBites
{	
	Ogre::Vector2 SdkTrayManager::convertCoords(Ogre::Vector3 tkrPos)
	{
		// convert from 3D world coords to 2D display coords
		int width = Ogre::OverlayManager::getSingleton().getViewportWidth();
		int height= Ogre::OverlayManager::getSingleton().getViewportHeight();						

		Ogre::Real x = width/2  + mPptToDispScale * (tkrPos.x - mOffset.x);
		Ogre::Real y = height/2 - mPptToDispScale * (tkrPos.y - mOffset.y); // flip the y-axis
		
		// clipping
		x = MIN( MAX(x,0), width );
		y = MIN( MAX(y,0), height);
		return Ogre::Vector2(x,y);
	}

	bool SdkTrayManager::injectRemoteMove(Ogre::Vector3 tkrPos)
	{						
		if (!mCursorLayer->isVisible()) return false;   // don't process if cursor layer is invisible		
		if (!isRemoteControl) return false;				// only process when using PPT to control the cursor

        Ogre::Vector2 cursorPos = convertCoords(tkrPos);		
		mCursor->setPosition(cursorPos.x, cursorPos.y);

		if (mExpandedMenu)   // only check top priority widget until it passes on
		{
			mExpandedMenu->_cursorMoved(cursorPos);
			return true;
		}

		if (mDialog)   // only check top priority widget until it passes on
		{
			mDialog->_cursorMoved(cursorPos);
			if (mOk) mOk->_cursorMoved(cursorPos);
			else
			{
				mYes->_cursorMoved(cursorPos);
				mNo->_cursorMoved(cursorPos);
			}
			return true;
		}

		Widget* w;

		for (unsigned int i = 0; i < 10; i++)
		{
			if (!mTrays[i]->isVisible()) continue;

			for (unsigned int j = 0; j < mWidgets[i].size(); j++)
			{
				w = mWidgets[i][j];
				if (!w->getOverlayElement()->isVisible()) continue;
				w->_cursorMoved(cursorPos);    // send event to widget
			}
		}

		if (mTrayDrag) return true;  // don't pass this event on if we're in the middle of a drag
		return false;
	}
		
	bool SdkTrayManager::injectRemoteDown(void)
	{		
		if (!mCursorLayer->isVisible()) return false;	// only process left button when stuff is visible
		if (!isRemoteControl) return false;				// only process when using PPT to control the cursor
		Ogre::Vector2 cursorPos(mCursor->getLeft(), mCursor->getTop());

		mTrayDrag = false;

		if (mExpandedMenu)   // only check top priority widget until it passes on
		{
			mExpandedMenu->_cursorPressed(cursorPos);
			if (!mExpandedMenu->isExpanded()) setExpandedMenu(0);
			return true;
		}

		if (mDialog)   // only check top priority widget until it passes on
		{
			mDialog->_cursorPressed(cursorPos);
			if (mOk) mOk->_cursorPressed(cursorPos);
			else
			{
				mYes->_cursorPressed(cursorPos);
				mNo->_cursorPressed(cursorPos);
			}
			return true;
		}

		for (unsigned int i = 0; i < 9; i++)   // check if mouse is over a non-null tray
		{
			if (mTrays[i]->isVisible() && Widget::isCursorOver(mTrays[i], cursorPos, 2))
			{
				mTrayDrag = true;   // initiate a drag that originates in a tray
				break;
			}
		}

		for (unsigned int i = 0; i < mWidgets[9].size(); i++)  // check if mouse is over a non-null tray's widgets
		{
			if (mWidgets[9][i]->getOverlayElement()->isVisible() &&
				Widget::isCursorOver(mWidgets[9][i]->getOverlayElement(), cursorPos))
			{
				mTrayDrag = true;   // initiate a drag that originates in a tray
				break;
			}
		}

		if (!mTrayDrag) return false;   // don't process if mouse press is not in tray

		for (unsigned int i = 0; i < 10; i++)
		{
			if (!mTrays[i]->isVisible()) continue;

			for (unsigned int j = 0; j < mWidgets[i].size(); j++)
			{
				Widget* w = mWidgets[i][j];
				if (!w->getOverlayElement()->isVisible()) continue;
				w->_cursorPressed(cursorPos);    // send event to widget

				SelectMenu* m = dynamic_cast<SelectMenu*>(w);
				if (m && m->isExpanded())       // a menu has begun a top priority session
				{
					setExpandedMenu(m);
					return true;
				}
			}
		}

		return true;   // a tray click is not to be handled by another party			
	}

	bool SdkTrayManager::injectRemoteUp(void)
	{													        
		if (!mCursorLayer->isVisible()) return false;	// only process left button when stuff is visible
		if (!isRemoteControl) return false;				// only process when using PPT to control the cursor

		Ogre::Vector2 cursorPos(mCursor->getLeft(), mCursor->getTop());

		if (mExpandedMenu)   // only check top priority widget until it passes on
		{
			mExpandedMenu->_cursorReleased(cursorPos);
			return true;
		}

		if (mDialog)   // only check top priority widget until it passes on
		{
			mDialog->_cursorReleased(cursorPos);
			if (mOk) mOk->_cursorReleased(cursorPos);
			else
			{
				mYes->_cursorReleased(cursorPos);
				// very important to check if second button still exists, because first button could've closed the popup
				if (mNo) mNo->_cursorReleased(cursorPos); 
			}
			return true;
		}

		if (!mTrayDrag) return false;    // this click did not originate in a tray, so don't process

		Widget* w;

		for (unsigned int i = 0; i < 10; i++)
		{
			if (!mTrays[i]->isVisible()) continue;

			for (unsigned int j = 0; j < mWidgets[i].size(); j++)
			{
				w = mWidgets[i][j];
				if (!w->getOverlayElement()->isVisible()) continue;
				w->_cursorReleased(cursorPos);    // send event to widget
			}
		}

		mTrayDrag = false;   // stop this drag
		return true;         // this click did originate in this tray, so don't pass it on			
	}	
	
	Ogre::Vector2 SdkTrayManager::getCursorPos()
	{
		return Ogre::Vector2(mCursor->getLeft(), mCursor->getTop());
	}
	
}