#ifndef MAINSCREEN_HPP_INCLUDED
#define MAINSCREEN_HPP_INCLUDED

#include "../../Core/Types/Box.hpp"
#include "../../Core/Types/Tile.hpp"
#include "../../Core/Classes/Character.hpp"
#include <cstdint>
#include <string>
#include <vector>

/**
* @brief A namespace containing various functions related to the Mainscreen
*/
namespace Mainscreen
{
    typedef enum SCREEN_STATE
    {
        LOGIN_SCREEN,
        LOBBY_SCREEN,
        CONNECTING,
        LOADING,
        HOPPING,
        PLAYING
    } SCREEN_STATE;

    typedef enum CROSSHAIR_STATE
    {
        NONE,
        YELLOW,
        RED
    } CROSSHAIR_STATE;

    /**
     * @brief Returns the current SCREEN_STATE
     * @return The current SCREEN_STATE
     */
    Mainscreen::SCREEN_STATE GetState();
    /**
    * @brief Returns the current CROSSHAIR_STATE
    * @return The current CROSSHAIR_STATE
    */
    Mainscreen::CROSSHAIR_STATE GetCrosshairState();

    /**
     * @brief Returns true if the Mainscreen SCREEN_STATE is PLAYING, LOADING, or HOPPING
     * @return True if the Mainscreen SCREEN_STATE is PLAYING, LOADING, or HOPPING
     */
    bool IsLoggedIn();
    /**
     * @brief Returns true if the player is moving
     * @return True if the player is moving
     * @details P.GetPoseAnimationID() != P.GetSubPoseAnimationID()
     */
    bool IsMoving();
    /**
    * @brief Returns true if the player is animating
    * @return True if the player is animating
    * @details P.GetAnimationID() != -1
    */
    bool IsAnimating();

    /**
     * @brief Returns The %mainscreen uptext found in the top left-hand corner
     * @return The %mainscreen uptext found in the top left-hand corner
     */
    std::string GetUpText();

    /**
     * @brief Returns true if the %mainscreen uptext is equal to the passed string
     * @param UpText String to compare
     * @return True if the %mainscreen uptext is equal to the passed string
     */
    bool IsUpText(const std::string& UpText);
    /**
     * @brief Returns true if the %mainscreen uptext is equal to any of the passed strings
     * @param UpTexts Strings to compare
     * @return True if the %mainscreen uptext is equal to any of the passed strings
     */
    bool IsUpText(const std::vector<std::string>& UpTexts);

    /**
     * @brief Returns true if the %mainscreen uptext contains the passed string
     * @param UpText String to check
     * @return True if the %mainscreen uptext contains the passed string
     */
    bool UpTextContains(const std::string& UpText);
    /**
     * @brief Returns true if the %mainscreen uptext contains any of the passed strings
     * @param UpTexts Strings to check
     * @return True if the %mainscreen uptext contains any of the passed strings
     */
    bool UpTextContains(const std::vector<std::string>& UpTexts);

    /**
     * @brief Extended function of UpTextContains
     * @description
     * This function will loop over (CheckTime) milliseconds, if the passed string isn't found within the uptext
     * it will go into a nested loop over (FailCheckTime) milliseconds, if the passed string still isn't found within the 'Fail' loop
     * the function will exit (false)
     * @param UpText String to check
     * @param CheckTime The passed string must be found in the mainscreen uptext for this long, to return true
     * @param FailCheckTime If the passed string isn't found within the mainscreen uptext,
     *  this is how long it will continue to try and find the passed string in the mainscreen uptext before returning false
     */
    bool UpTextContains(const std::string& UpText, std::uint32_t CheckTime, std::uint32_t FailCheckTime);
    /**
    * @brief Extended function of UpTextContains
    * @description
    * This function will loop over (CheckTime) milliseconds, if one of the passed strings isn't found within the uptext
    * it will go into a nested loop over (FailCheckTime) milliseconds, if one of the passed strings isn't still isn't found within the 'Fail' loop
    * the function will exit (false)
    * @param UpText String to check
     * @param CheckTime The passed string must be found in the mainscreen uptext for this long, to return true
     * @param FailCheckTime If the passed string isn't found within the mainscreen uptext,
     *  this is how long it will continue to try and find the passed string in the mainscreen uptext before returning false
    */
    bool UpTextContains(const std::vector<std::string>& UpTexts, std::uint32_t CheckTime, std::uint32_t FailCheckTime);

    /**
     * @brief Waits until the %mainscreen uptext is equal to the passed string
     * @see WaitFunc
     */
    bool WaitIsUpText(std::uint32_t Duration, std::uint32_t Step, const std::string& UpText);

    /**
     * @brief Waits until the %mainscreen uptext contains the passed string
     * @see UpTextContains
     * @see WaitFunc
     */
    bool WaitUpTextContains(std::uint32_t Duration, std::uint32_t Step, const std::string& UpText);
    /**
    * @brief Waits until the %mainscreen uptext contains any of the passed strings
    * @see UpTextContains
    * @see WaitFunc
    */
    bool WaitUpTextContains(std::uint32_t Duration, std::uint32_t Step, const std::vector<std::string>& UpTexts);

    /**
     * @brief Clicks on a tile on the %mainscreen
     * @return True if the tile was clicked
     * @return False if the distance from the tile is >= 8; !(Minimap::GetPosition().DistanceFrom(T) < 8) or it fails to click
     */
    bool ClickTile(const Tile& T);

    std::vector<Box> GetBlockingWidgetBoxes();
}

#endif // MAINSCREEN_HPP_INCLUDED
