#ifndef __TNMODEL_MODEL_H__
#define __TNMODEL_MODEL_H__

#include <vector>
#include <list>

#include "ModelShape.h"
#include <foundation/Math/Vertex.hpp>
#include "foundation/SharedPtr.h"

class TnMapTexture;

namespace Tn {

namespace openGLMap {
        
    /* 
       The purpose of this class is to contain the geometry for the vertices
       that has been generated for the VBO baker to operate on
    */

class Model
{
public:
    
    /*! Struct to hold information needed to build geometry later on 
     */
    struct ProjectedShape
    {
        ProjectedShape(Tn::Foundation::shared_ptr< std::vector<Tn::math::Point<3,double> > > const & projectedPoints,
                       eShapeType shapeType,
                       ShapeAttributes const & shapeAttributes) 
            : projectedPoints(projectedPoints),
              shapeType(shapeType),
              attributes(shapeAttributes) { assert(projectedPoints); }
            
        Tn::Foundation::shared_ptr< std::vector<Tn::math::Point<3,double> > > const & Points() const { return projectedPoints; }
        eShapeType Type() const { return shapeType; }
        ShapeAttributes const & Attributes() const { return attributes; }
        
        void SetAlphaValue(uint8_t alpha) { attributes.SetAlpha(alpha); }
        
        private:
            Tn::Foundation::shared_ptr< std::vector<Tn::math::Point<3,double> > > projectedPoints;
            eShapeType shapeType;
            ShapeAttributes attributes;
    };
    
    Model(); 
    
    //Model(TnOldCrazyModel const & oldModelStyle);

    eCoordType CoordinateType() const { return m_modelType; }
    
    std::list<ProjectedShape> const & ProjectedShapes() const { return m_projectedShapes; }
    
    Tn::math::Point3d const & Origin() const { return m_modelOrigin; }
    
    //methods for adding data
    void Add(Shape<LatLonAlt> const & shape);
    void Add(Shape<LatLonDelta> const & shape);
    void Add(Shape<XYZMetered> const & shape);
    
    
    //template <typename VERTEX>
    //void Add( std::vector<VERTEX> const & vertices, int primitiveType );
    
    //An unfortunate setter required to be able to dynamically change alpha value by client
    //Please don't use this function if you are a client, as it can be expensive
    void SetAlphaValue(uint8_t alpha);
    
    //void Add(KmlFile file);
    
private:
        
    //No copy
    Model& operator = (const Model& other);
	Model (const Model & other);     
    
    std::list<ProjectedShape> m_projectedShapes;
    
    //This private function/member variable pair do the book keeping to make sure
    //that no one attempts to mix and match vertex types
    bool CheckForIncorrectVertexAssignment(eCoordType vertexType);
    eCoordType m_modelType;
    
    Tn::math::Point3d m_modelOrigin;
    
};
    
    
}// namespace openGLMap
   
}// namespace Tn

#endif // __TNMODEL_MODEL_H__

