/* osgEarth
 * Copyright 2025 Pelican Mapping
 * MIT License
 */
#pragma once

#include <osgEarth/FeatureSource>

namespace osgEarth
{
    /**
     * FeatureSource that reads feature tiles from a parameterized "XYZ" source.
     */
    class OSGEARTH_EXPORT XYZFeatureSource : public TiledFeatureSource
    {
    public:
        class OSGEARTH_EXPORT Options : public TiledFeatureSource::Options {
        public:
            META_LayerOptions(osgEarth, Options, TiledFeatureSource::Options);
            OE_OPTION(URI, url);
            OE_OPTION(std::string, format);
            OE_OPTION(bool, esriGeodetic, false);
            OE_OPTION(bool, autoFallback, false);
            virtual Config getConfig() const;
        private:
            void fromConfig(const Config& conf);
        };

    public:
        META_Layer(osgEarth, XYZFeatureSource, Options, TiledFeatureSource, xyzfeatures);

        //! Location of the resource
        void setURL(const URI& value);
        const URI& getURL() const;

        //! Format of the geometry data (GeoJSON, GML)
        void setFormat(const std::string& value);
        const std::string& getFormat() const;

        //! Whether this is an ESRI style XYZ source, which needs it's LOD offset by 1 to match 
        //! the normal global-geodetic profile.
        void setEsriGeodetic(const bool& value);
        const bool& getEsriGeodetic() const;

        //! Whether a query for a TileKey higher than the max_level will
        //! automatically fall back to a query at the max_level.
        //! Default = false (an out-of bounds query returns nothing)
        void setAutoFallbackToMaxLevel(const bool& value);
        const bool& getAutoFallbackToMaxLevel() const;

        //! Inserts a full tile of features to the feature source.
        Status insert(const TileKey& key, const FeatureList& features, bool overwrite) override;

    public: // Layer

        Status openImplementation() override;

    protected:

        void init() override;

        FeatureCursor* createFeatureCursorImplementation(const Query& query, ProgressCallback* progress) const override;

    public: // FeatureSource

        bool isWritable() const override;

    protected:

        virtual ~XYZFeatureSource() { }

    private:
        std::string _template;
        std::string _rotateChoices;
        std::string _rotateString;
        std::string::size_type _rotateStart, _rotateEnd;
        mutable std::atomic_int _rotate_iter;
        
        bool getFeatures(const std::string& buffer, const TileKey& key, const std::string& mimeType, FeatureList& features) const;
        std::string getExtensionForMimeType(const std::string& mime) const;
        bool isGML( const std::string& mime ) const;
        bool isJSON( const std::string& mime ) const;
        URI createURL(const Query& query) const;
    };
} // namespace osgEarth

OSGEARTH_SPECIALIZE_CONFIG(osgEarth::XYZFeatureSource::Options);
