/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2015 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_SPLAT_OPTIONS
#define OSGEARTH_DRIVER_SPLAT_OPTIONS 1

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

namespace osgEarth { namespace Splat
{
    using namespace osgEarth;

    /**
     * Options governing the classification splatting engine.
     */
    class /*header-only*/ SplatOptions : public DriverConfigOptions
    {
    public:
        /** URI of the splat texture catalog description file;
            If you set a biomesURI, this will be ignored. */
        optional<URI>& catalogURI() { return _catalogURI; }
        const optional<URI>& catalogURI() const { return _catalogURI; }

        /** URI of a biomes definition file.
            Required is you do not specify a catalogURI. */
        optional<URI>& biomesURI() { return _biomesURI; }
        const optional<URI>& biomesURI() const { return _biomesURI; }
        
        /** URI of the legend that describes the values in the coverage layer
            and maps them to the catalog. Required. */
        optional<URI>& legendURI() { return _legendURI; }
        const optional<URI>& legendURI() const { return _legendURI; }

        /** Name of the coverage layer. The layer should be installed in the Map and
            should be marked as shared. */
        optional<std::string>& coverageLayerName() { return _coverageLayerName; }
        const optional<std::string>& coverageLayerName() const { return _coverageLayerName; }

        /** Whether to splat the terrain after drawing the map's image layers. The default
            setting is to splat first and then draw imagery. */
        optional<bool>& drawAfterImageLayers() { return _drawAfterImageLayers; }
        const optional<bool>& drawAfterImageLayers() const { return _drawAfterImageLayers; }

        /** Warping factor for coverage sampling. Please refer to
            SplatTerrainEffect::getCoverageWarpUniform() for details. */
        optional<float>& coverageWarp() { return _coverageWarp; }
        const optional<float>& coverageWarp() const { return _coverageWarp; }

        /** Blurring factor for coverage sampling. Please refer to
            SplatTerrainEffect::getCoverageBlurUniform() for details. */
        optional<float>& coverageBlur() { return _coverageBlur; }
        const optional<float>& coverageBlur() const { return _coverageBlur; }

        /** Level-of-detail offset for scaling the splat textures. */
        optional<int>& scaleLevelOffset() { return _scaleLevelOffset; }
        const optional<int>& scaleLevelOffset() const { return _scaleLevelOffset; }

        /** Whether to use bilinear sampling to smooth the coverage data.
            Default is true; set to false for higher performance. */
        optional<bool>& bilinearSampling() { return _bilinearSampling; }
        const optional<bool>& bilinearSampling() const { return _bilinearSampling; }

        /** Maximum distance from the camera at which to render detail splats. */
        optional<float>& detailMaxRange() { return _detailMaxRange; }
        const optional<float>& detailMaxRange() const { return _detailMaxRange; }

    public:
        SplatOptions( const ConfigOptions& opt =ConfigOptions() ) : DriverConfigOptions( opt )
        {
            setDriver( "splat" );

            // Set default values:
            _coverageWarp.init(0.01f);
            _coverageBlur.init(1.0f);
            _scaleLevelOffset.init(0);
            _drawAfterImageLayers.init(false);
            _bilinearSampling.init(true);
            _detailMaxRange.init(1000000.0f);

            fromConfig( _conf );
        }

        virtual ~SplatOptions() { }

    public:
        Config getConfig() const {
            Config conf = DriverConfigOptions::getConfig();
            conf.updateIfSet("catalog",  _catalogURI);
            conf.updateIfSet("biomes",   _biomesURI);
            conf.updateIfSet("legend",   _legendURI);
            conf.updateIfSet("coverage", _coverageLayerName );
            conf.updateIfSet("draw_after_image_layers", _drawAfterImageLayers);
            conf.updateIfSet("coverage_warp", _coverageWarp );
            conf.updateIfSet("coverage_blur", _coverageBlur );
            conf.updateIfSet("scale_level_offset", _scaleLevelOffset );
            conf.updateIfSet("bilinear_sampling", _bilinearSampling);
            conf.updateIfSet("detail_max_range", _detailMaxRange);
            return conf;
        }

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

    private:
        void fromConfig( const Config& conf ) {
            conf.getIfSet("catalog",  _catalogURI);
            conf.getIfSet("biomes",   _biomesURI);
            conf.getIfSet("legend",   _legendURI);
            conf.getIfSet("coverage", _coverageLayerName );
            conf.getIfSet("draw_after_image_layers", _drawAfterImageLayers);
            conf.getIfSet("coverage_warp", _coverageWarp );
            conf.getIfSet("coverage_blur", _coverageBlur );
            conf.getIfSet("scale_level_offset", _scaleLevelOffset );
            conf.getIfSet("bilinear_sampling", _bilinearSampling);
            conf.getIfSet("detail_max_range", _detailMaxRange);
        }

        optional<URI>         _catalogURI;
        optional<URI>         _biomesURI;
        optional<URI>         _legendURI;
        optional<std::string> _coverageLayerName;
        optional<bool>        _drawAfterImageLayers;
        optional<float>       _coverageWarp;
        optional<float>       _coverageBlur;
        optional<int>         _scaleLevelOffset;
        optional<bool>        _bilinearSampling;
        optional<float>       _detailMaxRange;
    };

} } // namespace osgEarth::Splat

#endif // OSGEARTH_DRIVER_SPLAT_OPTIONS
