/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
 * Copyright 2019 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_DRIVER_VPB_DRIVEROPTIONS
#define OSGEARTH_DRIVER_VPB_DRIVEROPTIONS 1

#include <osgEarth/Common>
#include <osgEarth/TileSource>
#include <osgEarth/URI>

namespace osgEarth { namespace Drivers
{
    using namespace osgEarth;

    class VPBOptions : public TileSourceOptions // NO EXPORT; header only
    {
    public: // types

        enum DirectoryStructure {
            DS_NESTED,
            DS_TASK,
            DS_FLAT
        };

    public: // properties

        optional<URI>& url() { return _url; }
        const optional<URI>& url() const { return _url; }

        optional<int>& primarySplitLevel() { return _primarySplitLevel; }
        const optional<int>& primarySplitLevel() const { return _primarySplitLevel; }

        optional<int>& secondarySplitLevel() { return _secondarySplitLevel; }
        const optional<int>& secondarySplitLevel() const { return _secondarySplitLevel; }

        optional<DirectoryStructure>& directoryStructure() { return _dirStruct; }
        const optional<DirectoryStructure>& directoryStructure() const { return _dirStruct; }

        optional<int>& layer() { return _layer; }
        const optional<int>& layer() const { return _layer; }

        optional<std::string>& layerSetName() { return _layerSetName; }
        const optional<std::string>& layerSetName() const { return _layerSetName; }

        optional<int>& numTilesWideAtLod0() { return _widthLod0; }
        const optional<int>& numTilesWideAtLod0() const { return _widthLod0; }

        optional<int>& numTilesHighAtLod0() { return _heightLod0; }
        const optional<int>& numTilesHighAtLod0() const { return _heightLod0; }

        optional<std::string>& baseName() { return _baseName; }
        const optional<std::string>& baseName() const { return _baseName; }

        optional<int>& terrainTileCacheSize() { return _terrainTileCacheSize; }
        const optional<int>& terrainTileCacheSize() const { return _terrainTileCacheSize; }
        
    public:
        VPBOptions( const TileSourceOptions& opt =TileSourceOptions() ) : TileSourceOptions( opt ),
            _primarySplitLevel( INT_MAX ),
            _secondarySplitLevel( INT_MAX ),
            _layer( 0 ),
            _widthLod0( 1 ),
            _heightLod0( 1 ),
            _dirStruct( DS_NESTED ),
            _terrainTileCacheSize(128)
        {
            setDriver( "vpb" );
            fromConfig( _conf );
        }

        /** dtor */
        virtual ~VPBOptions() { }

    public:
        Config getConfig() const {
            Config conf = TileSourceOptions::getConfig();
            conf.set("url", _url);
            conf.set("primary_split_level", _primarySplitLevel);
            conf.set("secondary_split_level", _secondarySplitLevel);
            conf.set("layer", _layer);
            conf.set("layer_setname", _layerSetName);
            conf.set("num_tiles_wide_at_lod_0", _widthLod0 );
            conf.set("num_tiles_high_at_lod_0", _heightLod0 );
            conf.set("base_name", _baseName );
            conf.set("terrain_tile_cache_size", _terrainTileCacheSize);
            if ( _dirStruct.isSet() ) {
                if ( _dirStruct == DS_FLAT ) conf.set("directory_structure", "flat");
                else if ( _dirStruct == DS_TASK ) conf.set("directory_structure", "task");
                else if ( _dirStruct == DS_NESTED ) conf.set("directory_structure", "nested");
            }
            return conf;
        }

    protected:
        void mergeConfig( const Config& conf ) {
            TileSourceOptions::mergeConfig( conf );
            fromConfig( conf );
        }

    private:
        void fromConfig( const Config& conf ) {
            conf.get("url", _url);
            conf.get("primary_split_level", _primarySplitLevel);
            conf.get("secondary_split_level", _secondarySplitLevel);
            conf.get("layer", _layer);
            conf.get("layer_setname", _layerSetName);
            conf.get("num_tiles_wide_at_lod_0", _widthLod0 );
            conf.get("num_tiles_high_at_lod_0", _heightLod0 );
            conf.get("base_name", _baseName);
            conf.get("terrain_tile_cache_size", _terrainTileCacheSize);
            
            std::string ds = conf.value("directory_structure");
            if ( ds == "flat" ) _dirStruct = DS_FLAT;
            else if ( ds == "task" ) _dirStruct = DS_TASK;
            else if ( ds == "nested" ) _dirStruct = DS_NESTED;
        }

        optional<URI>         _url;
        optional<std::string> _baseName, _layerSetName;
        optional<int>         _primarySplitLevel, _secondarySplitLevel, _layer, _widthLod0, _heightLod0;
        optional<DirectoryStructure> _dirStruct;
        optional<int> _terrainTileCacheSize;
    };

} } // namespace osgEarth::Drivers

#endif // OSGEARTH_DRIVER_VPB_DRIVEROPTIONS

