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

//! \file DtSymbolDecorationSettingsRecord.h
//! \brief Contains the DtSymbolDecorationSettingsRecord class declaration.
//! \ingroup makArchives

#pragma once

#include <makArchives/makArchives.h>
#include <makArchives/DtElementDefinitionRecord.h>

#include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/set.hpp>

#include <vrvCore/DtSymbologyEnums.h>

#include <set>
#include <string>
#include <unordered_map>

namespace makArchives
{

   //! \brief A DtSymbolDecorationSettingsRecord stores which symbol decorations
   //! are enabled/disabled.
   //! 
   //! This class has no virtual functions since it has no mechanism to be overriden.
   //! 
   //! \ingroup makArchives
   class DT_DLL_MAKARCHIVES DtSymbolDecorationSettingsRecord
   {
   public:
      using DecorationSet = std::set<std::string>;
      using NamedDecorationSetMap = std::unordered_map<std::string, DecorationSet>;
      
      using ModelSetSymbolDecorationMap = std::unordered_map<int, DecorationSet>;

      using TypeToDecorationMap = std::unordered_map<std::string, DecorationSet>;
      using ModelSetAndTypeSymbolDecorationMap = std::unordered_map<int, TypeToDecorationMap>;

   public:

      //! CTOR
      DtSymbolDecorationSettingsRecord();

      //! DTOR
      ~DtSymbolDecorationSettingsRecord();

      //! \brief Copy CTOR
      DtSymbolDecorationSettingsRecord( const DtSymbolDecorationSettingsRecord& orig );

      //! \brief Assignment Operator
      DtSymbolDecorationSettingsRecord& operator= ( const DtSymbolDecorationSettingsRecord& orig );

   public:
      //! @name Setting Accessors & Mutators
      //! @{
      //! \brief Get the map with enabled symbol decorations for all model sets
      virtual const ModelSetAndTypeSymbolDecorationMap& modelSetSymbolDecorationMap() const;

      //! \brief Get a list of enabled symbol decorations
      const DecorationSet& enabledDecorations( int modelSet, const std::string& type) const;

      //! \brief Set a symbol decoration enabled in the record
      void setDecorationEnabled( int modelSet, const std::string& type, const std::string& decorationCreator);

      //! \brief Set a symbol decoration disabled in the record
      void setDecorationDisabled( int modelSet, const std::string& type, const std::string& decorationCreator);

      //! \brief Disable all decorations in the record
      void setAllDisabled( int modelSet, const std::string& type);

      //! Decoration Sets associated with a name
      //!@{
      
      //! \brief Get a list of enabled symbol decorations
      const NamedDecorationSetMap& namedDecorationSetMap() const;

      //! \brief Add a named decoration set
      void addNamedDecorationSet(const std::string& decorationSetName, const DecorationSet& decorationSet);
      
      //! \brief Remove a named decoration set
      void removeNamedDecorationSet(const std::string& decorationSetName);

      //! \brief Clear all named decoration sets
      void clearNamedDecorationSets();

      //! @}

      //! Decorations for mouse over
      //!@{
      //! \brief Get the map with enabled symbol decorations for all model sets
      const ModelSetAndTypeSymbolDecorationMap& modelSetMouseOverSymbolDecorationMap() const;

      //! \brief Get a list of enabled symbol decorations for a model set
      const DecorationSet& enabledMouseOverDecorations( int modelSet, const std::string& type ) const;

      //! \brief Set a symbol decoration enabled in the record
      void setMouseOverDecorationEnabled( int modelSet, const std::string& type, const std::string& decorationCreator );

      //! \brief Set a symbol decoration disabled in the record
      void setMouseOverDecorationDisabled( int modelSet, const std::string& type, const std::string& decorationCreator );

      //! \brief Disable all decorations in the record
      void disableAllMouseOverDecorations( int modelSet, const std::string& type );
      //!@}

      //! Set the foreground color for the symbol decorations.
      void setForegroundColor( float r, float g, float b );
      //! Get the foreground color for the symbol decorations.
      void foregroundColor( float& r, float& g, float& b ) const;

      //! Set the background color for the symbol decorations.
      void setBackgroundColor( float r, float g, float b, float a );
      //! Get the background color for the symbol decorations.
      void backgroundColor( float& r, float& g, float& b, float& a ) const;

      //! Sets the altitude at which symbol decorations no longer appear.
      void setLodOutAltitude(double altitude);
      //! Gets the altitude at which symbol decorations no longer appear.
      double lodOutAltitude() const;

      //! Sets the MilStd icon standard (0 = MIL-STD-2525D, 1 = APP-6D, 999 = Font Icons (deprecated) ).
      void setMilSymbolStandard(makVrv::DtSymbologyStandard standard);
      //! Gets the MilStd icon standard (0 = MIL-STD-2525D, 1 = APP-6D, 999 = Font Icons (deprecated) ).
      makVrv::DtSymbologyStandard milSymbolStandard() const;

      //! Sets whether the symbol decoration text has a shadow or not.
      void setShadowText( bool enabled );
      //! Gets whether the symbol decoration text has a shadow or not.
      bool shadowText() const;

      //! Set whether the symbol decoration foreground/shadow colors should
      //! be controlled by force type
      void setColorByForce(bool enabled);

      //! Get whether symbol decoration foreground/shadow color is controlled
      //! by force type color
      bool colorByForce() const;

      //! Set whether the MIL-STD icon frame fill color should be controlled
      //! by force type
      void setColorSymbolByForce(bool enabled);

      //! Get whether MIL-STD icon frame fill color is controlled by force type
      bool colorSymbolByForce() const;

      //! \brief Set the outline color override state and both colors.
      //!
      //! When enabled, the MIL-STD frame outline uses these colors instead of the
      //! standard affiliation-based outline. Disabled by default to preserve SS36
      //! mine warfare outlines.
      void setSymbolOutlineColorOverride(bool enabled, float outR, float outG, float outB,
         float hlR, float hlG, float hlB);

      //! Get whether outline color override is enabled.
      bool symbolOutlineColorOverrideEnabled() const;

      //! Get the outline color.
      void symbolOutlineColor(float& r, float& g, float& b) const;

      //! Get the outline highlight color.
      void symbolOutlineHighlightColor(float& r, float& g, float& b) const;

      //! @}

   protected:

      //! Serialization
      friend class boost::serialization::access;

      //! When the class Archive corresponds to an output archive, the
      //! & operator is defined similar to <<.  Likewise, when the class Archive
      //! is a type of input archive the & operator is defined similar to >>.
      template<class Archive>
      void serialize( Archive & ar, const unsigned int version )
      {
         if( version >= 1 && version <= 6 )
         {
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationSettings );

            myModelSetSymbolDecorationMap.emplace( MODEL_SET_3D, mySymbolDecorationSettings );
            myModelSetSymbolDecorationMap.emplace( MODEL_SET_XR, mySymbolDecorationSettings );
            myModelSetSymbolDecorationMap.emplace( MODEL_SET_2D, mySymbolDecorationSettings );
         }
         if ( version >= 1 )
         {
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationBackgroundColorR );
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationBackgroundColorG );
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationBackgroundColorB );
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationBackgroundColorA );
         }

         if ( version >= 2 )
         {
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationForegroundColorR );
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationForegroundColorG );
            ar & BOOST_SERIALIZATION_NVP( mySymbolDecorationForegroundColorB );
            ar & BOOST_SERIALIZATION_NVP( myShadowTextFlag );
         }

         if ( version >= 3 )
         {
            ar & BOOST_SERIALIZATION_NVP( myColorByForceFlag );
         }

         if (version >= 4)
         {
            ar & BOOST_SERIALIZATION_NVP( myLodOutAltitude );
         }

         if( version >= 5 && version < 6 )
         {
            ar & BOOST_SERIALIZATION_NVP( myMouseOverSymbolDecorationSettings );

            myModelSetMouseOverSymbolDecorationMap.emplace( MODEL_SET_3D, myMouseOverSymbolDecorationSettings );
            myModelSetMouseOverSymbolDecorationMap.emplace( MODEL_SET_XR, myMouseOverSymbolDecorationSettings );
            myModelSetMouseOverSymbolDecorationMap.emplace( MODEL_SET_2D, myMouseOverSymbolDecorationSettings );
         }

         if (version >= 6)
         {
            ar& BOOST_SERIALIZATION_NVP(myNamedDecorationSettings);
         }

         if( version >= 7 && version < 8 )
         {
            ar & BOOST_SERIALIZATION_NVP( myModelSetSymbolDecorationMap );
            ar & BOOST_SERIALIZATION_NVP( myModelSetMouseOverSymbolDecorationMap );
         }

         if( version >= 8)
         {
            ar & BOOST_SERIALIZATION_NVP( myModelSetAndTypeSymbolDecorationMap );
            ar & BOOST_SERIALIZATION_NVP( myModelSetAndTypeMouseOverSymbolDecorationMap );
         }

         if( version >= 9 )
         {
            std::string milStdStr = milStdToString( myMilSymbolStandard );
            ar & boost::serialization::make_nvp( "myMilSymbolStandard", milStdStr );
            myMilSymbolStandard = milStdFromString( milStdStr );
            ar & BOOST_SERIALIZATION_NVP( myColorSymbolByForceFlag );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineColorOverrideEnabled );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineColorR );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineColorG );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineColorB );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineHighlightColorR );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineHighlightColorG );
            ar & BOOST_SERIALIZATION_NVP( mySymbolOutlineHighlightColorB );
         }
      }

   protected:
      //! \brief Convert a DtSymbologyStandard enum value to its settings-file string.
      static std::string milStdToString( makVrv::DtSymbologyStandard s )
      {
         switch( s )
         {
            case makVrv::DtSymbologyStandard::MilStd2525D: return "MilStd2525D";
            case makVrv::DtSymbologyStandard::MilStdApp6D: return "MilStdApp6D";
            case makVrv::DtSymbologyStandard::FontIcons:   return "FontIcons";
            default:                                       return "MilStdApp6D";
         }
      }

      //! \brief Parse a settings-file string back to a DtSymbologyStandard enum value.
      //!        Returns MilStdApp6D for any unrecognised string.
      static makVrv::DtSymbologyStandard milStdFromString( const std::string& s )
      {
         if( s == "MilStd2525D" ) return makVrv::DtSymbologyStandard::MilStd2525D;
         if( s == "MilStdApp6D" ) return makVrv::DtSymbologyStandard::MilStdApp6D;
         if( s == "FontIcons" )   return makVrv::DtSymbologyStandard::FontIcons;
         return makVrv::DtSymbologyStandard::MilStdApp6D;
      }

   protected:

      NamedDecorationSetMap myNamedDecorationSettings; //! Decoration sets tied to some name

      ModelSetAndTypeSymbolDecorationMap myModelSetAndTypeSymbolDecorationMap;
      ModelSetAndTypeSymbolDecorationMap myModelSetAndTypeMouseOverSymbolDecorationMap;

      //! depreciated
      //!@{
      ModelSetSymbolDecorationMap myModelSetSymbolDecorationMap;
      ModelSetSymbolDecorationMap myModelSetMouseOverSymbolDecorationMap;
      DecorationSet mySymbolDecorationSettings;
      DecorationSet myMouseOverSymbolDecorationSettings;
      //!@}
      float mySymbolDecorationForegroundColorR;
      float mySymbolDecorationForegroundColorG;
      float mySymbolDecorationForegroundColorB;

      float mySymbolDecorationBackgroundColorR;
      float mySymbolDecorationBackgroundColorG;
      float mySymbolDecorationBackgroundColorB;
      float mySymbolDecorationBackgroundColorA;

      double myLodOutAltitude;

      //! 0 = MIL-STD-2525D, 1 = APP-6D, 999 = Font Icons (deprecated)
      makVrv::DtSymbologyStandard myMilSymbolStandard;

      bool myShadowTextFlag;
      bool myColorByForceFlag;
      bool myColorSymbolByForceFlag;

      bool mySymbolOutlineColorOverrideEnabled;
      float mySymbolOutlineColorR;
      float mySymbolOutlineColorG;
      float mySymbolOutlineColorB;
      float mySymbolOutlineHighlightColorR;
      float mySymbolOutlineHighlightColorG;
      float mySymbolOutlineHighlightColorB;
   };
}

BOOST_CLASS_VERSION( makArchives::DtSymbolDecorationSettingsRecord, 9 )
