/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
 * Copyright 2020 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/>
 */
#pragma once

#include <osgEarth/Common>
#include <osgEarth/Feature>
#include <osgEarth/Filter>

namespace osgEarth { namespace Util
{
    /**
     * This filter will simplify geometries.
     */
    class OSGEARTH_EXPORT SimplifyFilter : public FeatureFilter
    {
    public:
        struct OSGEARTH_EXPORT Options : public ConfigOptions
        {
            Options(const ConfigOptions& co = {}) : ConfigOptions(co) {
                fromConfig(_conf);
            }

            OE_OPTION(double, tolerance, 0.0);
            OE_OPTION(bool, toleranceIsPercentage, false);
            OE_OPTION(bool, preserveTopology, true);
            OE_OPTION(bool, preserveAllFeatures, false);

            void fromConfig(const Config& conf) {
                conf.get("tolerance", tolerance(), toleranceIsPercentage());
                conf.get("preserve_topology", preserveTopology());
                conf.get("preserve_all_features", preserveAllFeatures());
            }

            Config getConfig() const {
                Config conf = ConfigOptions::getConfig();
                conf.key() = "simplify";
                conf.set("tolerance", tolerance(), toleranceIsPercentage());
                conf.set("preserve_topology", preserveTopology());
                conf.set("preserve_all_features", preserveAllFeatures());
                return conf;
            }
        };

    public:
        // Call this determine whether this filter is available.
        static bool isSupported();    

    public:
        SimplifyFilter() = default;
        SimplifyFilter(const Config& conf);

        void setTolerance(double value) {
            options().tolerance() = value;
            options().toleranceIsPercentage() = false;
        }

        void setToleranceAsPercentage(double value) {
            options().tolerance() = value;
            options().toleranceIsPercentage() = true;
        }

        void setPreserveTopology(bool value) {
            options().preserveTopology() = value;
        }

        void setPreserveAllFeatures(bool value) {
            options().preserveAllFeatures() = value;
        }

        virtual ~SimplifyFilter() { }

    public:
        virtual FilterContext push( FeatureList& input, FilterContext& context ); 

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

    protected:
        Options _options;
    };
} }
