/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2008-2010 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_OSGTERRAIN_ENGINE_NODE_H
#define OSGEARTH_ENGINE_OSGTERRAIN_ENGINE_NODE_H 1

#include <osgEarth/TerrainEngineNode>
#include <osgEarth/TextureCompositor>
#include <osgEarth/Map>
#include <osgEarth/Revisioning>
#include <osgEarth/TaskService>

#include "OSGTerrainOptions"
#include "OSGTileFactory"

#include <osg/Geode>
#include <osg/NodeCallback>

using namespace osgEarth;

class OSGTerrainEngineNode : public TerrainEngineNode
{
public:
    OSGTerrainEngineNode();
    OSGTerrainEngineNode( const OSGTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL );
    META_Node(osgEarth,OSGTerrainEngineNode);
    ~OSGTerrainEngineNode();

public: // TerrainEngineNode overrides    
    virtual void preInitialize( const Map* map, const TerrainOptions& options );
    virtual void postInitialize( const Map* map, const TerrainOptions& options );
    virtual void validateTerrainOptions( TerrainOptions& options );
    virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
    virtual void traverse( osg::NodeVisitor& );
    virtual osg::BoundingSphere computeBound() const;

public: // MapCallback adapter functions
    void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
    void onMapModelChanged( const MapModelChange& change ); // not virtual!

    UID getUID() const;
    OSGTileFactory* getTileFactory() const { return _tileFactory.get(); }
    class CustomTerrain* getTerrain() const { return _terrain; }

public: // statics    
    static void registerEngine( OSGTerrainEngineNode* engineNode );
    static void unregisterEngine( UID uid );
    static OSGTerrainEngineNode* getEngineByUID( UID uid );

private:
    void init();
    void syncMapModel();

    void addImageLayer( ImageLayer* layer );
    void addElevationLayer( ElevationLayer* layer );

    void removeImageLayer( ImageLayer* layerRemoved, unsigned int index );
    void removeElevationLayer( ElevationLayer* layerRemoved, unsigned int index );

    void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
    void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
    
    void updateElevation(CustomTile* tile);
    void installShaders();
    void updateTextureCombining();
    
private:
    osg::ref_ptr<OSGTileFactory> _tileFactory;
    //osg::ref_ptr<TextureCompositor> _texCompositor;
    class CustomTerrain* _terrain;
    UID _uid;
    osgEarth::Drivers::OSGTerrainOptions _terrainOptions;
    Revision _shaderLibRev;
    osg::ref_ptr<TaskServiceManager> _taskServiceMgr;

    // store a separate map frame for each of the traversal threads
    MapFrame* _update_mapf; // map frame for the main/update traversal thread
    MapFrame* _cull_mapf;   // map frame for the cull traversal thread
};

#endif // OSGEARTH_ENGINE_OSGTERRAIN_ENGINE_NODE_H
