#pragma once
#include "AftrConfig.h"
#ifdef AFTR_CONFIG_USE_IMGUI

#include "WOGUI.h"

//NOTE: To see all available ICONS that ImGui can print as text, browse the icons at:
//https://fontawesome.com/icons/categories/maps (AftrBurner uses the "SOLID" icons right now, not regular, or lite)
//To print an Icon you can just say:
//ImGui::Text( ICON_FA_FLOPPY_DISK " Save to File...); //a Floppy disk icon will appear before "Save to file"


#include <optional>
#include <filesystem>

namespace ImGui {
   class FileBrowser;
}

struct ImFont;

namespace Aftr
{

///This is the abstract base class from which children Dear ImGui classes inherit.
///See WOImGui.h/.cpp for a concrete example.
class WOImGuiAbstract : public WOGUI
{
public:
   //An abstract class cannot be instantiated, so there is no factory function to create an instance of this class.
   //static WOImGuiAbstract* New( WOGUI* parentWOGUI, float width = 1.0f, float height = 1.0f );
   virtual ~WOImGuiAbstract();
   virtual void render( const Camera& cam ) override;
   void renderGL32( const Camera& cam );
   void renderGL21( const Camera& cam );
   /// Abstract method user overrides to draw their gui. The example implementation
   /// defined here just draws the Demo that is included in Dear Im Gui. But it is
   /// a full featured demo that looks cool!
   virtual void drawImGui_for_this_frame() = 0;
   virtual void onUpdateWO() override;

   virtual bool handle_SDL_Event( const SDL_Event& e );
   virtual void onMouseDown( const SDL_MouseButtonEvent& mouse );
   virtual void onMouseUp( const SDL_MouseButtonEvent& mouse );
   virtual void onMouseWheelScroll( const SDL_MouseWheelEvent& e );
   virtual void onMouseMove( const SDL_MouseMotionEvent& mouse );
   virtual void onKeyDown( const SDL_KeyboardEvent& key );
   virtual void onKeyUp( const SDL_KeyboardEvent& key );
   virtual void onMouseDownSelection( const SDL_MouseButtonEvent& mouse );
   virtual void onMouseDownChildWasSelected( const SDL_MouseButtonEvent& mouse, WO* selectedChild );
   virtual void onResizeWindow( int newWidthInPixels, int newHeightInPixels ) override;

   ImFont const* getDefaultFont() const noexcept;

   //A file dialog browser. This is a plugin to ImGui from 
   // https://github.com/AirGuanZ/imgui-filebrowser/blob/master/imfilebrowser.h on 10 May 2020.
   //SLN: I wrapped the small amount of state that must persist across frames into some methods
   //and made the public calling behavior and usage very natural with Dear ImGui's immediate mode
   //expectations. The details/state remain hidden from all use cases of the file browser.
   //To Use the browser, simply repeat this pattern (See WOImGui.cpp for example):
   //Inside your WOImGui::drawImGui_for_this_frame():
   //   if( ImGui::Button( "Save a file!" ) )
   //      this->fileDialog_show_Save();
   //   if( this->fileDialog_has_selected_path() )
   //      this->selected_path = *this->fileDialog_get_selected_path(); //can only get one time, this clears the dialog's state!
   //*AND*, at the very end of your method, after the End() call:
   //   ImGui::End()
   //Add in this line of code to make the fileDialog update properly:
   //   this->fileDialog_update_after_ImGui_end_is_called(); //If you use any this->fileDialog_* methods, your drawImGui_for_this_frame() *must*
                                       //call this method *AFTER* you call to ImGui::End() or the FileDialog will not work as expected.
   
   ///Title must be unique and paired with corresponding calls to fileDialog_has/get. If you need to make the string
   ///unique but do not want the label to fully appear, use ## as a delimeter. For example, instead of saying
   ///fileDialog_show_SelectDirectory( "Selected Folder##dialog1" ); ///The ##dialog1 is used to make this unique, but not visible
   ///A valid filter could be std::vector{ {".h}, {".txt"}, {".cpp"} }. This would only show those extensions, no wild cards can be used.
   virtual void fileDialog_show_Save( const std::string& title, std::filesystem::path const& path = std::filesystem::current_path(), const std::vector< std::string >& filter = {} );
   
   ///Title must be unique and paired with corresponding calls to fileDialog_has/get. If you need to make the string
   ///unique but do not want the label to fully appear, use ## as a delimeter. For example, instead of saying
   ///fileDialog_show_SelectDirectory( "Selected Folder##dialog1" ); ///The ##dialog1 is used to make this unique, but not visible
   ///A valid filter could be std::vector{ {".h}, {".txt"}, {".cpp"} }. This would only show those extensions, no wild cards can be used.
   virtual void fileDialog_show_Open( const std::string& title, std::filesystem::path const& path = std::filesystem::current_path(), const std::vector< std::string >& filter = {} );

   ///Title must be unique and paired with corresponding calls to fileDialog_has/get. If you need to make the string
   ///unique but do not want the label to fully appear, use ## as a delimeter. For example, instead of saying
   ///fileDialog_show_SelectDirectory( "Selected Folder##dialog1" ); ///The ##dialog1 is used to make this unique, but not visible
   virtual void fileDialog_show_SelectDirectory( const std::string& title, std::filesystem::path const& path = std::filesystem::current_path(), const std::vector< std::string >& filter = {});

   ///Ensure the in passed title corresponds to a previously called fileDialog_show_* or this method will always return noopt
   virtual std::optional<std::filesystem::path> fileDialog_get_selected_path( const std::string& title );

   ///Ensure the in passed title corresponds to a previously called fileDialog_show_* or this method will always return noopt
   virtual bool fileDialog_has_selected_path( const std::string& title ) const noexcept;

   ///Called at the very end of WoImGui*::drawImGui_for_this_frame(), *After* ImGui::End() is called.
   ///Used internally to enable the file dialog to store its state.
   virtual void fileDialog_update_after_ImGui_end_is_called();

protected:
   virtual void onCreate( float width, float height );
   WOImGuiAbstract( WOGUI* parentWOGUI );

   ImFont* defaultFont = nullptr;
   ImFont* defaultFont_Bold = nullptr;

   std::unique_ptr< ImGui::FileBrowser > fileDialog;
   int64_t fileDialog_ID = 0; //Pairs the latest call to fileDialog_show_*( string ) with 
                      //the corresponding call to fileDialog_has/get_...( string ).
                      //Since File Dialogs *MUST BE MODAL*, we promise that any call to getDialog_has/get( string )
                      //maps to the most recent call to a fileDialog_show_*( string ) with that same string (hash value).
};

}

#endif
