/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
 * Copyright 2008-2014 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_REX_TERRAIN_DRAWABLE_H
#define OSGEARTH_REX_TERRAIN_DRAWABLE_H 1

#include "RenderBindings"
#include "DrawState"
#include "LayerDrawable"
#include <osgUtil/CullVisitor>

using namespace osgEarth;

namespace osgEarth { namespace REX
{
    //! Lookup table of each layer's layerdrawable
    using LayerDrawableTable = std::unordered_map<
        const Layer*,
        osg::ref_ptr<LayerDrawable>>;


    /**
     * Main data structure assembled by the TerrainCuller that contains
     * everything necessary to render one frame of the terrain.
     */
    class TerrainRenderData
    {
    public:
        struct PersistentData
        {
            osg::FrameStamp _lastCull;
            LayerDrawableTable _drawables;
        };

        TerrainRenderData() :
            _bindings(nullptr),
            _persistent(nullptr) 
        {
            //nop
        }

        /** Set up the map layers before culling the terrain */
        void reset(
            const Map* map,
            const RenderBindings& bindings,
            unsigned frameNum,
            PersistentData& pd,
            osgUtil::CullVisitor* cv,
            EngineContext* context);

        /** Optimize for best state sharing (when using geometry pooling). Returns total tile count. */
        unsigned sortDrawCommands();

        /** Add a Drawable for a layer. Add these in the order you wish to render them. */
        LayerDrawable* addLayerDrawable(const Layer*);

        /** Look up a LayerDrawable by its source layer UID. */
        LayerDrawable* layer(UID uid) { return _layersByUID[uid]; }

        // Draw state shared by all layers during one frame.
        DrawState::Ptr _drawState;

        // Layers of type RENDERTYPE_TERRAIN_PATCH
        PatchLayerVector& patchLayers() { return _patchLayers; }

        // transient:
        // ref_ptr's not necessary b/c of refs in _drawables above
        std::unordered_map<UID, LayerDrawable*> _layersByUID;
        std::vector<osg::ref_ptr<LayerDrawable>> _layerList;
        const RenderBindings* _bindings;
        PatchLayerVector _patchLayers; // Layers of type RENDERTYPE_TERRAIN_PATCH
        PersistentData* _persistent;
        EngineContext* _context;
    };

} } // namespace 

#endif // OSGEARTH_REX_TERRAIN_DRAWABLE_H
