#pragma once
#include "AftrConfig.h"
#ifdef AFTR_CONFIG_USE_IMGUI
#include "AftrImGuiIncludes.h"
#include "Mat4.h"
#include "Quat.h"
#include "AftrConfigurationParser.h"
#include <optional>

namespace Aftr
{
   class WO;

   ImVec2 operator+( ImVec2 const& a, ImVec2 const& b ) noexcept;
   ImVec2 operator-( ImVec2 const& a, ImVec2 const& b ) noexcept;

   namespace AftrImGui
   {
      extern const ImVec4 X_COLOR;// = { 1.0f,  0.3f, 0.3f, 1.0f };
      extern const ImVec4 Y_COLOR;// = { 0.3f,  1.0f, 0.3f, 1.0f };
      extern const ImVec4 Z_COLOR;// = { 0.25f, 0.5f, 0.5f, 1.0f };
      extern const ImVec4 W_COLOR;
      extern const ImVec4 RED_COLOR;
      extern const ImVec4 GREEN_COLOR;
      extern const ImVec4 BLUE_COLOR;
      extern const ImVec4 WHITE_COLOR;
      extern const ImVec4 YELLOW_COLOR;
      //Draws a Roll, Pitch, Yaw slider triplet initialized with the DCM. If the user modifies
      //any angle, the DCM is updated accordingly AND true is returned; otherwise, returns false
      //and the DCM is unmodified. If a "modification" occurs, but the total change of any
      //angle is less than epsilon degrees, the behavior will return false with NO modification.
      bool draw_DCM_as_RPY_compass_heading( Mat4& dcm, std::string const& text = "", float const epsilon_deg = 0.001f);

      bool draw_Vector_XYZ_input( Vector& v, std::string const& text, int numDecimals = 3, std::string const& hint = "val:" );

      //When the mouse hovers over the (?) or the in passed iconTxt, a popup will occur
      //containing the text within desc.
      void draw_ToolTip( std::string const& desc );
      //Same as above, but let's user replace the default iconf "(?)" with any desired text.
      void draw_ToolTip( std::string const& desc, std::string const& iconTxt );
      //Immediately draws a popup text window without making an icon.
      void draw_PopupText( std::string const& desc );

      //Returns true iff the user chooses the TRUE option. Common example is a Yes / No dialog box.
      //An empty optional is returned if the user did not click either button, but the box was drawn.
      //This is needed since the box may be draw for many frames before the user selects their desired option.
      std::optional<bool> draw_Binary_ConfirmationBox( std::string const& button_text_beforeConfirmation = "Confirm this button click",
                                        std::string const& textual_question = "Are you sure you want to continue?",
                                        std::string const& true_button_text  = "Yes",
                                        std::string const& false_button_text = " No" );

      template< typename T >
      void draw_Vector_Colored( VectorT<T> const& vec, unsigned int const numDigits = 3,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR );

      template< typename T >
      void draw_Vector_w_mag_Colored( VectorT<T> const& vec, unsigned int const numDigits = 3,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR,
         ImVec4 const& magnitude_color = W_COLOR );

      template< typename T >
      void draw_Quat_Colored( QuatT<T> const& q, unsigned int const numDigits = 3,
         ImVec4 const& W_color = W_COLOR, //imaginary component
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR );

      template< typename T >
      void draw_Pose_as_XYZ_RPY_Colored( Mat4T<T> const& pose, unsigned int const numDigits = 3,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR,
         ImVec4 const& Yaw_color =   Z_COLOR,
         ImVec4 const& Pitch_color = Y_COLOR,
         ImVec4 const& Roll_color =  X_COLOR );

      template< typename T >
      void draw_Pose_as_XYZ_RPY_w_mag_Colored( Mat4T<T> const& pose, unsigned int const numDigits = 3,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR,
         ImVec4 const& Yaw_color = Z_COLOR,
         ImVec4 const& Pitch_color = Y_COLOR,
         ImVec4 const& Roll_color = X_COLOR,
         ImVec4 const& magnitude_color = W_COLOR );

      template< typename T >
      void draw_Mat4_Colored( Mat4T<T> const& pose, unsigned int const numDigits = 7,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR);

      template< typename T >
      void draw_Rotation_Info_from_Mat4( Mat4T<T> const& pose, unsigned int const numDigits = 7,
         ImVec4 const& X_color = X_COLOR,
         ImVec4 const& Y_color = Y_COLOR,
         ImVec4 const& Z_color = Z_COLOR );

      struct ColoredString
      {
         std::string str;
         ImVec4 color = WHITE_COLOR;
      };

      // Given a map and a specific key, this creates an ImGui popup that let's the user select any value
      // from the list of values on the right hand side of the key. The list of values is delimited by the
      // delimiter.
      // For example the expected map type is a map of string -> string. So,
      // "image_format"=".png;.bmp;.pgm;.jpg"
      // The key is "image_format", an ImGui popup will appear listing .png .bmp .pgm and .jpg. If the user
      // clicks on one of the values, that string is returned. If the user cancels / closes the popup, nullopt
      // is returned.
      //Given an AftrConfigurationParser::map_type (just like the one contained inside AftrConfigurationWithFileName)
      //which is an std::map< std::string, std::string, std::less<> > (as of 2 April).
      std::optional<std::string> draw_select_value_from_MapKey_using_ImGuiPopup(
         std::string const& ImGui_Button_Text, //Button containing this text that will trigger a list to appear
         std::string const& map_key, //list contains all delim separated strings found at this key in the map
         std::string_view delimeter, //could use something like a ; or , or whatever is used to split the values
         AftrConfigurationParser::map_type const& map ); //map that contains ; separated values at key 'map_key'
      //char const *const ImGuiPopup_Name ); //ImGui requires a unique ID - hard coded until actually needed

   }
}
#endif
