/* osgEarth
* Copyright 2008-2014 Pelican Mapping
* MIT License
*/
#pragma once

#include "Common"
#include "GeometryPool"
#include "Loader"
#include "Unloader"
#include "TileNode"
#include "TileNodeRegistry"
#include "RenderBindings"
#include "TileDrawable"

#include <osgEarth/TerrainTileModel>
#include <osgEarth/Progress>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/Horizon>

#include <osgUtil/CullVisitor>

using namespace osgEarth;

#define ENGINE_CONTEXT_TAG "osgEarth::Rex::EngineContext"

namespace osgEarth {
    class FrameClock;
}

namespace osgEarth { namespace REX
{
    class SelectionInfo;

    class EngineContext : public osg::Referenced
    {
    public:
        EngineContext(
            const Map* map,
            TerrainEngineNode* engine,
            GeometryPool* geometryPool,
            Merger* merger,
            TileNodeRegistry::Ptr tiles,
            const RenderBindings& renderBindings,
            const SelectionInfo& selectionInfo,
            const FrameClock* clock);

        Merger* getMerger() const { return _merger; }

        const RenderBindings& getRenderBindings() const { return _renderBindings; }

        GeometryPool* getGeometryPool() const { return _geometryPool; }

        osg::ref_ptr<const Map> getMap() const;

        // only call this variant when it's safe to do so (update, cull).
        osg::ref_ptr<TerrainEngineNode> getEngine() { return osg::ref_ptr<TerrainEngineNode>(_terrainEngine); }

        TileNodeRegistry::Ptr tiles() const { return _tiles; }

        const SelectionInfo& getSelectionInfo() const { return _selectionInfo; }

        const TerrainOptionsAPI& options() const { return _options; }

        ProgressCallback* progress() const { return _progress.get(); }        

        ModifyBoundingBoxCallback* getModifyBBoxCallback() const { return _bboxCB.get(); }

        bool getUseTextureBorder() const { return false; }

        const FrameClock* getClock() const { return _clock; }

        TextureArena* textures() const { return _textures.get(); }

    protected:

        virtual ~EngineContext() { }

    public:
        
        osg::observer_ptr<TerrainEngineNode>  _terrainEngine;
        osg::observer_ptr<const Map>          _map;
        TileNodeRegistry::Ptr                 _tiles;
        TerrainOptionsAPI                     _options;
        const RenderBindings&                 _renderBindings;
        GeometryPool*                         _geometryPool;
        Merger*                               _merger;
        const SelectionInfo&                  _selectionInfo;
        osg::Timer_t                          _tick;
        int                                   _tilesLastCull;
        osg::ref_ptr<ProgressCallback>        _progress;
        osg::ref_ptr<ModifyBoundingBoxCallback> _bboxCB;
        const FrameClock*                     _clock;
        osg::ref_ptr<TextureArena>            _textures;
    };

} } // namespace osgEarth::Drivers::RexTerrainEngine
