/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2013 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_ENGINE_MP_TILE_NODE
#define OSGEARTH_ENGINE_MP_TILE_NODE 1

#include "Common"
#include "TileModel"
#include <osg/MatrixTransform>

namespace osgEarth_engine_mp
{
    using namespace osgEarth;

    /**
     * Node that represents a single terrain tile that was compiled from
     * a TileModel (and corresponds to one TileKey). The matrixtransform
     * localizes the TileNode within the terrain.
     */
    class TileNode : public osg::MatrixTransform
    {
    public:
        /**
         * Constructs a new tile node
         */
        TileNode( const TileKey& key, const TileModel* model );

        /**
         * The tilekey associated with this tile
         */
        const TileKey& getKey() const { return _key; }

        /**
         * Whether the tile consists of "real" data
         * (versus upsampled fallback data).
         */
        void setHasRealData( bool value ) { _realData = value; }
        bool hasRealData() const { return _realData; }

        /**
         * True if this is a valid tile node.
         * Subclass may override (see InvalidTileNode)
         */
        virtual bool isValid() const { return true; }

        /**
         * Access the source data model that built this tile.
         */
        const TileModel* getTileModel() { return _model.get(); }

        /**
         * Sets the last traversal frame manually. A parent TileGroup
         * will call this to prevent the born-time from resetting 
         * when traversing the tile's children.
         */
        void setLastTraversalFrame(unsigned frame);


    public: // OVERRIDES

        virtual void traverse( class osg::NodeVisitor& nv );

        virtual void releaseGLObjects(osg::State* state) const;

        virtual osg::BoundingSphere computeBound() const;

    protected:

        virtual ~TileNode() { }

        TileKey                 _key;
        bool                    _realData;
        osg::Uniform*           _bornUniform;
        mutable osg::Uniform*   _keyUniform;
        osg::ref_ptr<const TileModel> _model;
        osg::Uniform*           _tileParentMatrixUniform;
        unsigned                _lastTraversalFrame;
        double                  _bornTime;
    };


    typedef std::vector< osg::ref_ptr<TileNode> > TileNodeVector;


    /**
     * Marker class - the engine will return one of these when a TileNode
     * load fails permanently. It will also blacklist the TileKey.
     */
    class InvalidTileNode : public TileNode
    {
    public:
        InvalidTileNode(const TileKey& key) : TileNode(key, 0L) { }
        bool isValid() const { return false; }
    protected:
        virtual ~InvalidTileNode() { }
    };


} // namespace osgEarth_engine_mp

#endif // OSGEARTH_ENGINE_MP_TILE_NODE
