#ifndef _RUENTITYSKYDOME_H_
#define _RUENTITYSKYDOME_H_

// Rune entity base
#include "../../Scene/Base/RuEntityBase.h"
#include "../../Scene/Base/RuEntityContainer.h"
#include "../../Scene/Base/RuEntityModel.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

class CRuSkyDome : public CRuEntity
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	enum CloudTransitionMode
	{
		ctNONE,
		ctPENDING,
		ctEXECUTING
	};

	struct HorizonCloudDesc
	{
		REAL								m_age;
		REAL								m_fadeStartTime;
		REAL								m_theta;								//!< Position on the cloud ring
		REAL								m_thetaGradient;						//!< Theta gradient, in radians per second

		CRuMaterial*						m_material;
		CRuModel*							m_model;

		REAL								m_sizeT;
		REAL								m_sizeTGradient;

		INT32								m_typeIndex;							//!< Cloud type 0 (vertical axis on the texture map)
		INT32								m_sizeIndex0;							//!< Cloud "size" 0 (horizontal axis on the texture map)
		INT32								m_sizeIndex1;							//!< Cloud "size" 1 (horizontal axis on the texture map)
		REAL								m_vsConstants[8];
	};

	struct OverheadCloudDesc
	{
		REAL								m_age;
		REAL								m_fadeStartTime;
		REAL								m_omega;
		REAL								m_omegaGradient;
		REAL								m_rho;
		REAL								m_rhoGradient;
		REAL								m_theta;								//!< Position on the cloud ring
		REAL								m_thetaGradient;						//!< Theta gradient, in radians per second

		CRuMaterial*						m_material;
		CRuModel*							m_model;

		REAL								m_sizeT;
		REAL								m_sizeTGradient;

		INT32								m_typeIndex;							//!< Cloud type 0 (vertical axis on the texture map)
		INT32								m_sizeIndex0;							//!< Cloud "size" 0 (horizontal axis on the texture map)
		INT32								m_sizeIndex1;							//!< Cloud "size" 1 (horizontal axis on the texture map)
		REAL								m_vsConstants[8];
	};

	// Dome geometry settings
	INT32									m_horizontalSegments;
	INT32									m_verticalSegments;
	float									m_domeCenterY;

	float									m_domeGradientT;
	float									m_domeGradientTDelta;
	IRuTexture*								m_domeGradientTexture0;
	IRuTexture*								m_domeGradientTexture1;					//!< 

	CRuModel*								m_domeModel;							//!< Skydome model
	CRuMesh*								m_domeMesh;								//!< Dome mesh
	CRuMaterial*							m_domeMaterial;							//!< Dome material

	// Horizon cloud
	INT32									m_horizonCloudCount;

	INT32									m_horizonCloudTypeCount;				//!< Total number of cloud type variations in the texture map
	INT32									m_horizonCloudSizeCount;				//!< Total number of cloud size variations in the texture map

	CloudTransitionMode						m_horizonCloudTransitionMode;
	IRuTexture*								m_horizonCloudTexture0;
	IRuTexture*								m_horizonCloudTexture1;					//!< 

	REAL									m_horizonCloudColorT;
	REAL									m_horizonCloudColorTDelta;
	CRuColor4								m_horizonCloudColor0;
	CRuColor4								m_horizonCloudColor1;

	CRuMesh*								m_horizonCloudMesh;

	CRuFrame*								m_horizonCloudModel;

	CRuArrayList<HorizonCloudDesc>			m_horizonClouds;

	// Overhead cloud
	INT32									m_overheadCloudCount;

	INT32									m_overheadCloudTypeCount;				//!< Total number of cloud type variations in the texture map
	INT32									m_overheadCloudSizeCount;				//!< Total number of cloud size variations in the texture map

	CloudTransitionMode						m_overheadCloudTransitionMode;
	IRuTexture*								m_overheadCloudTexture0;
	IRuTexture*								m_overheadCloudTexture1;					//!< 

	REAL									m_overheadCloudColorT;
	REAL									m_overheadCloudColorTDelta;
	CRuColor4								m_overheadCloudColor0;
	CRuColor4								m_overheadCloudColor1;

	CRuMesh*								m_overheadCloudMesh;

	CRuFrame*								m_overheadCloudModel;

	CRuArrayList<OverheadCloudDesc>			m_overheadClouds;

	// Bounds
	CRuSphere								m_localBounds;							//!< Local space bounding sphere

public:
											CRuSkyDome();
	virtual									~CRuSkyDome();

	// IRuObject serialization
	virtual BOOL							SerializeFrom(IRuStream *stream);
	virtual BOOL							SerializeTo(IRuStream *stream);

	// Entity interface
	virtual BOOL							ResetStates();
	virtual BOOL							Update(float elapsedTime);
	void									UpdateHorizonClouds(float elapsedTime);
	void									UpdateOverheadClouds(float elapsedTime);
/*
	// Required subclass interface
	virtual void							UpdateEntityTransform();
	virtual void							UpdateEntityBounds();
*/
	BOOL									Initialize(INT32 horzSegments = 4, INT32 vertSegments = 10, float vertSweep = 90.0f, float radius = 3000.0f, float vertScale = 1.0f, float horzCompression = 2.0f, INT32 cloudPlaneSegments = 16);

	// stuff...
	void									SetCamera(CRuCamera *viewCamera);

	BOOL									IsInTransition() const;

	void									SetSkyDomeGradientTexture(IRuTexture *gradientTexture);
	void									TransitionSkyDomeGradientTexture(IRuTexture *gradientTexture, float transitionTime);

	void									SetHorizonCloudTexture(IRuTexture *cloudPlaneTexture);
	void									TransitionHorizonCloudTexture(IRuTexture *cloudPlaneTexture, float transitionTime);

	void									SetHorizonCloudColor(const CRuColor4 &cloudColor);
	void									TransitionHorizonCloudColor(const CRuColor4 &cloudColor, REAL transitionTime);

	void									SetHorizonCloudCount(INT32 cloudCount);

	void									SetOverheadCloudTexture(IRuTexture *cloudPlaneTexture);
	void									TransitionOverheadCloudTexture(IRuTexture *cloudPlaneTexture, float transitionTime);

	void									SetOverheadCloudColor(const CRuColor4 &cloudColor);
	void									TransitionOverheadCloudColor(const CRuColor4 &cloudColor, REAL transitionTime);

	void									SetOverheadCloudCount(INT32 cloudCount);
};

// ************************************************************************************************************************************************************

#pragma managed

#endif
