#pragma once

#include "Mix/Scene/IViewCamera.h"
#include "Mix/Private/Scene/Common/RendererObject.h"
#include "Mix/Private/Scene/Common/Camera.h"

namespace Mix{ namespace Scene{ namespace Common{

	class ViewCamera : public Mix::Scene::IViewCamera, public Mix::Scene::Common::Camera
	{
	public:
		static ViewCamera* CreateInstance( const Mix::Scene::CAMERA_CONFIG& config );

	private:
		Mix::Vector3 m_LocalEye;
		Mix::Quaternion m_Rot;
		Mix::Matrix4x4 m_RotMat;
		Float32 m_Distance;

	private:
		ViewCamera( const Mix::Scene::CAMERA_CONFIG& config );
		virtual ~ViewCamera( void );

		void UpdateViewMat( void );

	public:
		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::IViewCamera
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual void SetView( const Mix::Vector3& at, const Mix::Quaternion& rotation, Float32 distance );
		virtual void SetAt( const Mix::Vector3& at );
		virtual const Mix::Quaternion& GetRotation( void ) const;
		virtual const Mix::Matrix4x4& GetRotationMatrix( void ) const;
		virtual void SetRotation( const Mix::Quaternion& rotation );
		virtual Float32 GetDistance( void ) const;
		virtual void SetDistance( Float32 distance );

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::ICamera
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual UInt32 GetID( void ) const;

		virtual const Mix::Scene::CAMERA_CONFIG& GetConfig( void ) const;
		virtual Boolean SetConfig( const Mix::Scene::CAMERA_CONFIG& config );

		virtual const Mix::Vector4& GetBackgroundColor( void ) const;
		virtual void SetBackgroundColor( const Mix::Vector4& color );

		virtual Mix::Graphics::TEXTURE_FILTER_TYPE GetFilterType( void ) const;
		virtual void SetFilterType( Mix::Graphics::TEXTURE_FILTER_TYPE type );

		virtual Float32 GetFovY( void ) const;
		virtual Float32 GetDefaultAspect( void ) const;
		virtual Float32 GetAspect( void ) const;
		virtual Float32 GetNearZ( void ) const;
		virtual Float32 GetFarZ( void ) const;
		virtual const Mix::Matrix4x4& GetProjectionMatrix( void ) const;
		virtual void SetProjection( Float32 fovY, Float32 nearZ, Float32 farZ );
		virtual void SetProjection( Float32 fovY, Float32 aspect, Float32 nearZ, Float32 farZ );
		virtual void SetProjection( Float32 fovY, UInt32 width, UInt32 height, Float32 nearZ, Float32 farZ );

		virtual const Mix::Vector3& GetEye( void ) const;
		virtual const Mix::Vector3& GetAt( void ) const;
		virtual const Mix::Vector3& GetViewVector( void ) const;
		virtual const Mix::Vector3& GetViewForward( void ) const;
		virtual const Mix::Vector3& GetViewUpward( void ) const;
		virtual const Mix::Vector3& GetViewCrossDirection( void ) const;
		virtual const Mix::Matrix4x4& GetViewMatrix( void ) const;

		virtual const Mix::Geometry::Frustum& GetFrustum( void ) const;

		virtual const Mix::Matrix4x4& GetViewProjectionMatrix( void ) const;
		virtual const Mix::Matrix4x4& GetInvViewProjectionMatrix( void ) const;

		virtual const Mix::Matrix4x4& GetBillboardMatrix( void ) const;
		virtual const Mix::Matrix4x4& GetBillboardMatrixY( void ) const;

		virtual Boolean IsUnderWater( void ) const;

		virtual Mix::Point Project( const Mix::Vector3& pos ) const;
		virtual Mix::Point Project( const Mix::Point& screenPos, const Mix::Vector3& pos ) const;
		virtual Mix::Point Project( const Mix::Rectangle& screenRect, const Mix::Vector3& pos ) const;

		virtual Mix::Vector3 Unproject( const Mix::Point& pos, Float32 z ) const;
		virtual Mix::Vector3 Unproject( const Mix::Point& screenPos, const Mix::Point& pos, Float32 z ) const;
		virtual Mix::Vector3 Unproject( const Mix::Rectangle& screenRect, const Mix::Point& pos, Float32 z ) const;

		virtual Boolean DragObject( const Mix::Point& pos );
		virtual Boolean DragObject( const Mix::Point& screenPos, const Mix::Point& pos );
		virtual Boolean DragObject( const Mix::Rectangle& screenRect, const Mix::Point& pos );

		virtual void Update( Float32 dt );
		virtual Boolean Draw( void );

		virtual const Mix::Scene::ICamera::VISIBILITY_SETTINGS& GetVisiblitySettings( void ) const;
		virtual void SetVisiblitySettings( const Mix::Scene::ICamera::VISIBILITY_SETTINGS& settings );

		virtual Boolean IsAmbientOcclusionEnabled( void ) const;
		virtual void SetAmbientOcclusionEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::AMBIENT_OCCLUSION_SETTINGS& GetAmbientOcclusionSettings( void ) const;
		virtual void SetAmbientOcclusionSettings( const Mix::Scene::ICamera::AMBIENT_OCCLUSION_SETTINGS& settings );
		virtual Boolean GetAmbientOcclusionTexture( Mix::Graphics::ITexture** ppTex );
		virtual void SetAmbientOcclusionTexture( Mix::Graphics::ITexture* pTex );

		virtual Boolean IsShadowMappingEnabled( void ) const;
		virtual void SetShadowMappingEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::SHADOW_MAPPING_SETTINGS& GetShadowMappingSettings( void ) const;
		virtual void SetShadowMappingSettings( const Mix::Scene::ICamera::SHADOW_MAPPING_SETTINGS& settings );

		virtual const Mix::Scene::ICamera::LUMINOSITY_SETTINGS& GetLuminositySettings( void ) const;
		virtual void SetLuminositySettings( const Mix::Scene::ICamera::LUMINOSITY_SETTINGS& settings );
		virtual UInt32 ResumeLuminosityAdaptation( void );
		virtual UInt32 SusupendLuminosityAdaptation( void );
		virtual UInt32 GetLuminosityAdaptationSuspendCount( void ) const;
		virtual void ForceLuminosityAdaptation( void );
		virtual void SetLuminosityAdaptation( Float32 lum );

		virtual Boolean IsBloomEnabled( void ) const;
		virtual void SetBloomEnabled( Boolean state );
		virtual UInt32 GetBloomOverflowNum( void ) const;
		virtual const Mix::Scene::ICamera::BLOOM_OVERFLOW& GetBloomOverflow( UInt32 index ) const;
		virtual void SetBloomOverflow( UInt32 index, const Mix::Scene::ICamera::BLOOM_OVERFLOW& overflow );
		virtual const Mix::Scene::ICamera::BLOOM_SETTINGS& GetBloomSettings( void ) const;
		virtual void SetBloomSettings( const Mix::Scene::ICamera::BLOOM_SETTINGS& settings );

		virtual Boolean IsLightShaftsEnabled( void ) const;
		virtual void SetLightShaftsEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::LIGHT_SHAFTS_SETTINGS& GetLightShaftsSettings( void ) const;
		virtual void SetLightShaftsSettings( const Mix::Scene::ICamera::LIGHT_SHAFTS_SETTINGS& settings );
		virtual Boolean GetLightShaftsTexture( Mix::Graphics::ITexture** ppTex );
		virtual void SetLightShaftsTexture( Mix::Graphics::ITexture* pTex );

		virtual Boolean IsLensFlareEnabled( void ) const;
		virtual void SetLensFlareEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::LENS_FLARE_SETTINGS& GetLensFlareSettings( void ) const;
		virtual void SetLensFlareSettings( const Mix::Scene::ICamera::LENS_FLARE_SETTINGS& settings );
		virtual Boolean GetLensFlareTexture( Mix::Scene::ICamera::LENS_FLARE_TEXTURE_TYPE type, Mix::Graphics::ITexture** ppTexture );
		virtual void SetLensFlareTexture( Mix::Scene::ICamera::LENS_FLARE_TEXTURE_TYPE type, Mix::Graphics::ITexture* pTexture );

		virtual Boolean IsFilmicEnabled( void ) const;
		virtual void SetFilmicEnabled( Boolean state );
		virtual Mix::Scene::ICamera::FILMIC_TYPE GetFilmicType( void ) const;
		virtual Boolean GetFilmicSettings( void* pSettings, UInt32 size ) const;
		virtual Boolean SetFilmicType( Mix::Scene::ICamera::FILMIC_TYPE type, const void* pSettings, UInt32 size );

		virtual Boolean IsGammaEnabled( void ) const;
		virtual void SetGammaEnabled( Boolean state );
		virtual const Mix::Vector3& GetGammaValue( void ) const;
		virtual void SetGammaValue( const Mix::Vector3& value );
		virtual void SetGammaValue( Float32 value );

		virtual Boolean IsMotionBlurEnabled( void ) const;
		virtual void SetMotionBlurEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::MOTION_BLUR_SETTINGS& GetMotionBlurSettings( void ) const;
		virtual void SetMotionBlurSettings( const Mix::Scene::ICamera::MOTION_BLUR_SETTINGS& settings );
		virtual Boolean IsMotionBlurActivated( void ) const;
		virtual UInt32 GetMotionBlurCurrentAmount( void ) const;

		virtual Boolean IsChromatismEnabled( void ) const;
		virtual void SetChromatismEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::CHROMATISM_SETTINGS& GetChromatismSettings( void ) const;
		virtual void SetChromatismSettings( const Mix::Scene::ICamera::CHROMATISM_SETTINGS& settings );

		virtual Boolean IsDofEnabled( void ) const;
		virtual void SetDofEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::DOF_SETTINGS& GetDofSettings( void ) const;
		virtual void SetDofSettings( const Mix::Scene::ICamera::DOF_SETTINGS& settings );

		virtual Boolean IsLensDistortionEnabled( void ) const;
		virtual void SetLensDistortionEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::DISTORTION_SETTINGS& GetLendDistortionSettings( void ) const;
		virtual void SetLendDistortionSettings( const Mix::Scene::ICamera::DISTORTION_SETTINGS& settings );

		virtual Boolean IsVignetteEnabled( void ) const;
		virtual void SetVignetteEnabled( Boolean state );
		virtual const Mix::Scene::ICamera::VIGNETTE_SETTINGS& GetVignetteSettings( void ) const;
		virtual void SetVignetteSettings( const Mix::Scene::ICamera::VIGNETTE_SETTINGS& settings );

		virtual Mix::Scene::ICamera::ANTIALIASING_TYPE GetAntiAliasingType( void ) const;
		virtual void SetAntiAliasingType( Mix::Scene::ICamera::ANTIALIASING_TYPE type );

		virtual void Debug_SetFillType( Mix::Graphics::FILL_TYPE type );
		virtual Mix::Graphics::FILL_TYPE Debug_GetFillType( void ) const;
		virtual void Debug_SetDrawMethod( Mix::Scene::DEBUG_DRAW_METHOD method );
		virtual Mix::Scene::DEBUG_DRAW_METHOD Debug_GetDrawMethod( void ) const;
		virtual void Debug_SetDrawFlags( UInt32 flags );
		virtual UInt32 Debug_GetDrawFlags( void ) const;
		virtual const Mix::Scene::ICamera::DEBUG_DRAW_FILIMIC_SETTINGS& Debug_GetDrawFilmicSettings( void ) const;
		virtual void Debug_SetDrawFilmicSettings( const Mix::Scene::ICamera::DEBUG_DRAW_FILIMIC_SETTINGS& settings );
		virtual UInt32 Debug_GetProfile( UInt32 type, void* pProf, UInt32 size ) const;
		virtual UInt32 Debug_GetImageNum( UInt32 type ) const;
		virtual Boolean Debug_GetImage( UInt32 type, UInt32 index, Mix::Graphics::ITexture** ppTexture );

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::IRendererObject
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Mix::Scene::IRendererObject::TYPE GetType( void ) const;
		virtual Boolean IsRendering( void ) const;

	public:
		static const wchar_t* FAILED_CREATE;
	};

}}}
