/******************************************************************************
** Copyright(c) 2026 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/

//! \file EffectMapExtension.h
//! \brief Extension for loading the effect mapping effect on demand
//! \ingroup osgdb_osgearth_effectmap
#ifndef OSGEARTH_EFFECTMAP_EXTENSION
#define OSGEARTH_EFFECTMAP_EXTENSION 1

#include "EffectMapOptions.h"
#include "EffectMapTerrainEffect.h"
#include <osgEarth/Extension>
#include <osgEarth/MapNode>
#include <set>

#include <osg/observer_ptr>
#include <vrvUtil/DtSignalConnectionManager.h>

namespace makVrv
{
   class DtDe;
}

namespace osgEarth
{
   namespace EffectMap
   {
      using namespace osgEarth;

      /**
       * Extension for loading the effect mapping effect on demand.
       * Some effects such as rain/snow can have their creation deferred and triggered
       * by weather state change signals.
       */
      class EffectMapExtension : public Extension,
         public ExtensionInterface<MapNode>,
         public EffectMapOptions
      {
      public:
         META_Object(osgearth_ext_EffectMap, EffectMapExtension);

         // CTORs
         EffectMapExtension();
         EffectMapExtension(const EffectMapOptions& options);

         // DTOR
         virtual ~EffectMapExtension();

      protected: // Object
         //! protected copy constructor that does nothing
         EffectMapExtension(const EffectMapExtension& rhs, const osg::CopyOp& op) : myEffect(NULL) { }


      public: // Extension

         //! setup the db options for this osgEarth extention
         virtual void setDBOptions(const osgDB::Options* dbOptions);

         //! get the configuration options for this extention (typecast of this object)
         virtual const ConfigOptions& getConfigOptions() const { return *this; }


      public: // ExtensionInterface<MapNode>

         //! connect to the map node. This creates the effect and sets up the shaders
         bool connect(MapNode* mapNode);

         //! disconnect from the map node.
         bool disconnect(MapNode* mapNode);


      protected: // Object
         //! \brief add the effect map layer as the shared image layer to the map
         virtual void addEffectMapLayer(MapNode* mapNode);

         //!generate a texture uniform name based on a static int that is the effect shader id
         //! this needs to match the one created by the effect
         virtual const std::string generateShareTexUniformName() const;

         //!generate a texture matrix uniform name based on a static int that is the effect shader id
         //! this needs to match the one created by the effect
         virtual const std::string generateShareTexMatUniformName() const;

         virtual makVrv::DtDe* findDtDeInOptions() const;

         //! connect to signals that listen for effect map weather state changes.
         virtual void connectSignals();

         //! slot for handling changes to the rain state.
         //! This will create the rain mask effect map layer and effect as needed.
         virtual void slot_effectMapRainStateChanged(bool enabled);

         //! slot for handling changes to the snow state.
         //! This will create the snow mask effect map layer and effect as needed.
         virtual void slot_effectMapSnowStateChanged(bool enabled);

         //! Determines if the creation of the effect map layer and effect should be deferred until
         //! the state is enabled. This is used to avoid creating the effect map layer and effect
         //! if the rain and snow effects are never enabled.
         virtual bool shouldDeferCreation() const;

         //! A helper to create the effect map layer and effect based on the effect type.
         virtual bool createLayerAndEffect(MapNode* mapNode);

      protected:

         osg::observer_ptr<osgEarth::MapNode> myMapNode;
         makVrv::DtSignalConnectionManager myConnections;

      private:

         osg::ref_ptr<const osgDB::Options>   myDbOptions;
         EffectMapTerrainEffect*  myEffect;
         static std::set<EffectMapOptions::EffectType> theEffectTypes;
         static int theEffectMapCount;
      };

   }
} // namespace osgEarth::EffectMap

#endif // OSGEARTH_EFFECTMAP_EXTENSION
