/*
--------------------------------------------------------------------------------
This source file is part of SkyX.
Visit ---

Copyright (C) 2009 Xavier Verguín González <xavierverguin@hotmail.com>
                                           <xavyiy@gmail.com>

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
--------------------------------------------------------------------------------
*/

#include "SkyxMoonManager.h"
#include "Skyx.h"

namespace SkyX
{

	MoonManager::MoonManager(SkyX *s)
	{
		mSkyX = s;
		mMoonSize = 0.1f;

    mMoonSceneNode = mSkyX->getSceneManager()->getRootSceneNode()->createChildSceneNode();
		mMoonBillboard = mSkyX->getSceneManager()->createBillboardSet("SkyXMoonBillboardSet", 1);
    mMoonBillboard->setMaterialName(mSkyX->getGPUManager()->getMoonMaterialName());
		mMoonBillboard->setRenderQueueGroup(Ogre::RENDER_QUEUE_SKIES_EARLY+1);
		mMoonBillboard->setCastShadows(false);
		mMoonBillboard->createBillboard(Ogre::Vector3(0,0,0));
		mMoonSceneNode->attachObject(mMoonBillboard);
		_updateMoonBounds();
	}

	MoonManager::~MoonManager()
	{
		mMoonSceneNode->detachAllObjects();
		mMoonSceneNode->getParentSceneNode()->removeAndDestroyChild(mMoonSceneNode->getName());
		mMoonSceneNode = 0;

		mSkyX->getSceneManager()->destroyBillboardSet(mMoonBillboard);
		mMoonBillboard = 0;
	}

	void MoonManager::update()
	{
    // TODO JEFF DELETE
	}

	void MoonManager::setMoonSize(const Ogre::Real& MoonSize)
	{
		mMoonSize = MoonSize;
		_updateMoonBounds();
	}

	void MoonManager::_updateMoonBounds()
	{
		float radius = _def_MaxFarClipDistance * 0.95f;
    float size = radius*mMoonSize;

		mMoonBillboard->setDefaultDimensions(size, size);
		mMoonBillboard->setBounds(Ogre::AxisAlignedBox(-size/2, -size/2, -size/2, size/2,  size/2,  size/2), 1);
		mMoonSceneNode->_updateBounds();
	}

  void MoonManager::_notifyCameraChanged(Ogre::Camera* newCamera)
  {
    // Handling infinite far clip
    Ogre::Real cameraCurrentFarClipDistance = newCamera->getFarClipDistance();
    if((cameraCurrentFarClipDistance == 0) || (cameraCurrentFarClipDistance > _def_MaxFarClipDistance))
      cameraCurrentFarClipDistance = _def_MaxFarClipDistance;

    // Compute moon billboard size
		float radius = cameraCurrentFarClipDistance * 0.95f;
    float size = radius * mMoonSize;

    // compute horizon relative position
    Ogre::Vector3 moonRelativePos = -(mSkyX->getAstronomicalModel()->getMoonDirection() * radius);
    
    // Scale the mesh & update position
    Ogre::Real billboardScale = radius / _def_MaxFarClipDistance;
    mMoonSceneNode->setScale(billboardScale, billboardScale, billboardScale);
    Ogre::Vector3 cameraPostion = newCamera->getDerivedPosition();
    Ogre::Vector3 moonPosition(cameraPostion + moonRelativePos);
    mMoonSceneNode->setPosition(moonPosition);

		if (moonRelativePos.y < -size/2)
		{
			mMoonSceneNode->setVisible(false);
		}
		else
		{
			mMoonSceneNode->setVisible(true);
      Ogre::Pass*  ogreMoonPass = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName("SkyX_Moon"))->getTechnique(0)->getPass(0);

      Ogre::GpuProgramParametersSharedPtr parameters;
      parameters = ogreMoonPass->getVertexProgramParameters();
      parameters->setNamedConstant("uSkydomeCenter", newCamera->getDerivedPosition());
      
      float moonPhase = mSkyX->getAstronomicalModel()->getMoonPhase();
      parameters = ogreMoonPass->getFragmentProgramParameters();
      parameters->setNamedConstant("uMoonPhase", moonPhase);
		}
  }
}
