
#ifndef __WFX_SCENE_NODE_H__
#define __WFX_SCENE_NODE_H__

#include <WFX/WFXIncludes.h>

#include <WFX/scene/Spatial.h>
#include <WFX/scene/Color.h>
#include <WFX/math/Vector2.h>
#include <WFX/scene/Material.h>

namespace WFX {

    namespace scene {

        /**
         * abstract scenegraph node
         * any node should extend this class
         * possible children would be octree nodes...
         */
        class AbstractNode : public WFX::scene::Spatial {
            public:
                /**
                 * Ctor/Dtor
                 */
                AbstractNode() : Spatial() {};
                virtual ~AbstractNode() {};

                /** render */
                virtual void draw(renderer::Renderer* Renderer) = 0;

                /** accept a SceneGraphVisitor */
                virtual void accept(SceneGraphVisitor& v) = 0;
            protected:
            private:
        };

        /**
         * basic scenegraph node
         * A node does by definition not contain any
         * geometrical information (as in: Vertices)
         */
        class Node : public WFX::scene::AbstractNode {
            public:
                /**
                 * Ctor/Dtor
                 */
                Node();
                virtual ~Node() {
                    destroy();
                }

                /** render */
                virtual void draw(renderer::Renderer* Renderer);
                
                /** add a Child to this node */
                void addChild(Spatial* c);

                /** updates */
                virtual void updateDown();
                
                /** 
                 * destroys this subtree
                 */
                void destroy();

                /** returns number of children */
                UInt size() {
                    return Children.size();
                }
                   
                /** accept a SceneGraphVisitor */
                void accept(SceneGraphVisitor& v);
            protected:
                friend class SceneGraphPrinter;
                friend class SceneGraphTransformer;
                friend class SceneGraphSerializer;
                friend class OctreeBuilder;
                friend class BoundingCubeFinder;
                /** list of children */
                std::list<Spatial*> Children;

        };

        /**
         * abstract base class for all Nodes representing any geometrical data
         * GeometryNodes are Scenegraph leafs, they do not have any children
         * associated with them
         */
        class GeometryNode : public WFX::scene::AbstractNode {
            public:
                /** render flags */
                bool DrawVertexNormals;
                 
                /**
                 * Ctor/Dtor
                 */
                GeometryNode();
                GeometryNode(UInt vc, math::Vector3* v, math::Vector3* n, Color* c, math::Vector2* t) : AbstractNode(),
                                                                                                        VertexCount(vc),
                                                                                                        Vertices(v),
                                                                                                        Normals(n),
                                                                                                        Colors(c),
                                                                                                        TexCoords(t) {
                    MyMaterial = NULL;
                }
                
                virtual ~GeometryNode() {
                    delete[] Vertices;
                    delete[] Normals;
                    delete[] Colors;
                    delete[] TexCoords;
                }

                /** returns the vertices */
                inline math::Vector3* getVertices() {
                    return Vertices;
                }
                /** returns vertex count */
                inline UInt getVertexCount() {
                    return VertexCount;
                }
                /** returns colors */
                inline Color* getColors() {
                    return Colors;
                }
                /** returns vertex normals */
                inline math::Vector3* getNormals() {
                    return Normals;
                }
                /** returns texture coordinates */
                inline math::Vector2* getTexCoords() {
                    return TexCoords;
                }
                /** returns the Material */
                inline Material* getMaterial() {
                    return MyMaterial;
                }

                /** 
                 * sets all Vertices' color to the given color
                 * make sure there is enough memory allocated for the colors, might
                 * cause segfaults otherwise
                 */
                void setColor(const WFX::scene::Color& c);

                /** sets the Material */
                inline void setMaterial(Material* m) {
                    MyMaterial = m;
                }
                /** sets the vertices */
                inline void setVertices(math::Vector3* v) {
                    Vertices = v;
                }
                /** sets vertex count */
                inline void  setVertexCount(UInt vc) {
                    VertexCount = vc;
                }
                /** sets colors */
                inline void setColors(scene::Color* c) {
                    Colors = c;
                }
                /** sets vertex normals */
                inline void setNormals(math::Vector3* n) {
                    Normals = n;
                }
                /** sets texture coordinates */
                inline void setTexCoords(math::Vector2* t) {
                    TexCoords = t;
                }

                /** (re)calculate vertex normals */
                virtual void calcNormals() = 0;

                /** (re)calculate ModelBound */
                virtual void calcModelBound();

                /** updates */
                virtual void updateDown();

            protected:
                /** number of vertices */
                UInt VertexCount;
                /** vertices */
                math::Vector3* Vertices;
                /** vertex normals */
                math::Vector3* Normals;
                /** colors */
                Color* Colors;
                /** texture coordinates */
                math::Vector2* TexCoords;
                /** material */
                WFX::scene::Material* MyMaterial;

                
        };

    }

}


#endif //include guard


