/* osgEarth
 * Copyright 2025 Pelican Mapping
 * MIT License
 */
#ifndef OSGEARTH_SILVERLINING_API_WRAPPER
#define OSGEARTH_SILVERLINING_API_WRAPPER 1

#include "Common"
#include <osg/Vec3>
#include <osg/GL>
#include <stdint.h> // for uintptr_t


namespace osgEarth { namespace SilverLining
{
    class Atmosphere;

    enum CloudTypes
    {
        CIRROCUMULUS,               /*!<  High planar cloud puffs */
        CIRROSTRATUS,               /*!<  High, thin uniform planar cloud */
        CIRRUS_FIBRATUS,            /*!<  High, thicker and fibrous clouds that signal changing weather */
        STRATUS,                    /*!<  Low clouds represented as a slab */
        CUMULUS_MEDIOCRIS,          /*!<  Low, puffy clouds on fair days */
        CUMULUS_CONGESTUS,          /*!<  Large cumulus clouds, built for performance. */
        CUMULUS_CONGESTUS_HI_RES,   /*!<  Large cumulus clouds represented with high-resolution puff textures. */
        CUMULONIMBUS_CAPPILATUS,    /*!<  Big storm clouds. */
        STRATOCUMULUS,              /*!<  Low, dense, puffy clouds with some sun breaks between them. Implemented with GPU ray-casting. */
        STRATOCUMULUS_PARTICLES,    /*!<  Low, dense, puffy clouds with some sun breaks between them. Implemented with billboard particles. */
        TOWERING_CUMULUS,           /*!<  Very large, tall cumulus clouds in the process of becoming a thunderstorm.*/
        SANDSTORM,                  /*!<  A "haboob" cloud of dust intended to be positioned at ground level. */
        NUM_CLOUD_TYPES             /*!<  Total number of cloud types. */
    };

    class OSGEARTHSILVERLINING_EXPORT CloudLayer
    {
    public:
        enum PrecipitationTypes
        {
            NONE,
            RAIN,
            DRY_SNOW,
            WET_SNOW,
            SLEET,
            NUM_PRECIP_TYPES
        };

    public:
        CloudLayer(uintptr_t handle) : _handle(handle) { }

        void SetEnabled(bool value);
        bool GetEnabled() const;

        void SetBaseWidth(double value);
        double GetBaseWidth() const;

        void SetBaseLength(double value);
        double GetBaseLength() const;

        void SetBaseAltitude(double value);
        double GetBaseAltitude() const;

        void SetThickness(double value);
        double GetThickness() const;

        void SetDensity(double value);
        double GetDensity() const;

        void SetLayerPosition(double east, double north);
        void GetLayerPosition(double& east, double& north) const;

        void SetIsInfinite(bool value);
        bool GetIsInfinite() const;

        void SetWind(double windEast, double windSouth);
        void GetWind(double& windEast, double& windSouth) const;

        void SetCloudWrapping(bool value);
        bool GetCloudWrapping() const;

        void SetFadeTowardEdges(bool value);
        bool GetFadeTowardEdges() const;

        void SetAlpha(double value);
        double GetAlpha() const;

        void SetCloudAnimationEffects(double, bool, int c=0, int d=0);
        void GetCloudAnimationEffects(double&, bool&, int&, int&);

        void SeedClouds(Atmosphere&);

        uintptr_t _handle;
    };

    class OSGEARTHSILVERLINING_EXPORT CloudLayerFactory
    {
    public:
        static CloudLayer Create(int kind, Atmosphere& atmos);
    };

    class OSGEARTHSILVERLINING_EXPORT WindVolume
    {
    public:
        WindVolume();
        WindVolume(double windSpeed, double direction);

        void SetMinAltitude(double metersMSL);
        double GetMinAltitude() const;
        void SetMaxAltitude(double metersMSL);
        double GetMaxAltitude() const;
        void SetWindSpeed(double metersPerSecond);
        double GetWindSpeed() const;
        void SetDirection(double degreesFromNorth);
        double GetDirection() const;

    private:
        double _minAltitude;
        double _maxAltitude;
        double _windSpeed;
        double _direction;
    };

    class OSGEARTHSILVERLINING_EXPORT AtmosphericConditions
    {
    public:
        int AddCloudLayer(class CloudLayer&);
        bool RemoveCloudLayer(int layerHandle);
        void RemoveAllCloudLayers();

        void SetVisibility(double vis);
        double GetVisibility() const;

        void SetTurbidity(double turb);
        double GetTurbidity() const;

        void SetLightPollution(double wattsPerSqm);
        double GetLightPollution() const;

        void SetPrecipitation(int type, double rate);

        int SetWind(double metersPerSecond, double degreesFromNorth);
        int SetWind(const WindVolume& windVolume);
        bool RemoveWindVolume(int windVolumeHandle);
        void ClearWindVolumes();

        enum ConditionPresets
        {
            FAIR = 0,
            PARTLY_CLOUDY,
            MOSTLY_CLOUDY,
            OVERCAST
        };
        void SetPresetConditions(ConditionPresets preset, Atmosphere& atm);

        void EnableTimePassage(bool enabled, long relightFrequencyMS);

        void GetLocation(double &latitude, double &longitude, double &altitude) const;
        void SetFog(double density, const osg::Vec3 &color);
    public:
        AtmosphericConditions(uintptr_t handle) : _handle(handle) { }
        uintptr_t _handle;
    };

    class OSGEARTHSILVERLINING_EXPORT Atmosphere
    {
    public:
        void EnableLensFlare(bool value);
        bool GetLensFlareEnabled() const;

        enum SkyModel
        {
            PREETHAM,
            HOSEK_WILKIE
        };

        void SetSkyModel(SkyModel skyModel);
        SkyModel GetSkyModel() const;

        void SetGamma(double gamma);
        double GetGamma() const;

        void SetInfraRedMode(bool infraRed);
        bool GetInfraRedMode() const;

        AtmosphericConditions GetConditions() const;

        bool GetFogEnabled() const; 
        void GetFogSettings(float &density, osg::Vec3 &color) const;
        void GetHorizonColor(float yaw, float pitch, osg::Vec3 &color) const;
        bool GetEnvironmentMap(GLuint &environmentMapTex, int facesToRender = 6, bool floatingPoint = false, void* cameraID = 0,bool drawClouds = true, bool drawSunAndMoon = true, bool isGeocentric = false) const;
        void SetHaze(const osg::Vec3 &color, double depth, double density);
    public:
        Atmosphere(uintptr_t handle) : _handle(handle) { }
        uintptr_t _handle;
    };

} } // namespace osgEarth::SilverLining

#endif // OSGEARTH_SILVERLINING_API_WRAPPER
