
#ifndef __WFX_RENDERER_RENDERER_H__
#define __WFX_RENDERER_RENDERER_H__

#include <WFX/WFXIncludes.h>

#include <WFX/lang/Singleton.h>
#include <WFX/renderer/RenderTarget.h>
#include <WFX/renderer/Camera.h>
#include <WFX/renderer/Viewport.h>
#include <WFX/renderer/RenderContext.h>

#include <WFX/math/Matrix4.h>

#include <WFX/scene/TriMesh.h>
#include <WFX/math/Sphere.h>
#include <WFX/math/Cube.h>

namespace WFX {

    namespace renderer {

        /**
         * abstract Renderer base class 
         * implementing renderers must implement HLHSR!
         */
        class Renderer : public WFX::lang::Singleton<Renderer> {
            public:
                /** maximum/minimum coordinates when using ortho-mode */
                static Int OrthoMax;
                    
                /**
                 * Ctor
                 */
                Renderer() {}
                /**
                 * Dtor
                 */
                virtual ~Renderer() {}

                /**
                 * sets the Rendertarget to render to
                 */
                void setRenderTarget(RenderTarget* p) {
                    CurrentTarget = p;
                }
                
                /** sets the Camera to render from */
                virtual void setCamera(Camera* p) {
                    CurrentCamera = p;
                }
                Camera* getCamera() {
                    return CurrentCamera;
                }
                /** 
                 * sets the current Viewport 
                 * implementations must set the Act* Values of the Viewport
                 */
                virtual void setViewport(Viewport* v) {
                    CurrentViewport = v;
                }
                Viewport* getViewport() {
                    return CurrentViewport;
                }
               
                /** 
                 * notify the Renderer of a new rendering operation
                 */
                virtual void beginRenderOp();
                
                /** 
                 * notify the Renderer that the rendering operation ended
                 */
                virtual void endRenderOp() {
                }
                
                /** apply a rendercontext */
                virtual void setRenderContext(const RenderContext& r) = 0;
                /** set a color */
                virtual void setColor(const WFX::scene::Color& c) = 0;

                /** switches to ortho mode matching the current viewport */
                virtual void orthoMode() = 0;
                /** switches back to the camera mode matching the current viewport */
                virtual void perspectiveMode() = 0;
                
                /**
                 * return the projection matrix as 4*4 Reals
                 * @param: dest - the destination pointer
                 */
                virtual void getProjectionMatrix(WFX::math::Matrix4& dest) = 0;
                /**
                 * return the modelview matrix as 4*4 Reals
                 * @param: dest - the destination pointer
                 */
                virtual void getModelViewMatrix(WFX::math::Matrix4& dest) = 0;

                /**
                 * set Material
                 */
                virtual void setMaterial(WFX::scene::Material& m) = 0;

                /**
                 * These draw* methods must be implemented by all child classes
                 */
                virtual void drawTriMesh(WFX::scene::TriMesh& m) = 0;
                virtual void drawSphere(WFX::math::Sphere& s) = 0;
                virtual void drawWireCube(WFX::math::Cube& c) = 0;
                
            protected:
                /** the current Rendertarget to render to */
                WFX::renderer::RenderTarget* CurrentTarget;
                /** the current Camera to render from */
                WFX::renderer::Camera* CurrentCamera;
                /** the current Viewport to render to */
                WFX::renderer::Viewport* CurrentViewport;
            
            private:

        };

    }

}


#endif //include guard


