#ifndef OPENMW_MISCELLANEOUSAPI_HPP
#define OPENMW_MISCELLANEOUSAPI_HPP

#include "../Types.hpp"

#define MISCELLANEOUSAPI \
    {"DoesFileExist",               MiscellaneousFunctions::DoesFileExist},\
    {"GetCaseInsensitiveFilename",  MiscellaneousFunctions::GetCaseInsensitiveFilename},\
    \
    {"GetLastPlayerId",             MiscellaneousFunctions::GetLastPlayerId},\
    \
    {"GetCurrentMpNum",             MiscellaneousFunctions::GetCurrentMpNum},\
    {"SetCurrentMpNum",             MiscellaneousFunctions::SetCurrentMpNum},\
    \
    {"GetPluginEnforcementState",   MiscellaneousFunctions::GetPluginEnforcementState},\
    {"SetPluginEnforcementState",   MiscellaneousFunctions::SetPluginEnforcementState},\
    \
    {"LogMessage",                  MiscellaneousFunctions::LogMessage},\
    {"LogAppend",                   MiscellaneousFunctions::LogAppend}

class MiscellaneousFunctions
{
public:

    /**
    * \brief Check whether a certain file exists.
    *
    * This will be a case sensitive check on case sensitive filesystems.
    *
    * Whenever you want to enforce case insensitivity, use GetCaseInsensitiveFilename() instead.
    *
    * \return Whether the file exists or not.
    */
    static bool DoesFileExist(const char *filePath) noexcept;

    /**
    * \brief Get the first filename in a folder that has a case insensitive match with the filename
    * argument.
    *
    * This is used to retain case insensitivity when opening data files on Linux.
    *
    * \return The filename that matches.
    */
    static const char *GetCaseInsensitiveFilename(const char *folderPath, const char *filename) noexcept;

    /**
    * \brief Get the last player ID currently connected to the server.
    *
    * Every player receives a unique numerical index known as their player ID upon joining the
    * server.
    *
    * \return The player ID.
    */
    static unsigned int GetLastPlayerId() noexcept;

    /**
    * \brief Get the current (latest) mpNum generated by the server.
    *
    * Every object that did not exist in an .ESM or .ESP data file and has instead been placed or
    * spawned through a server-sent packet has a numerical index known as its mpNum.
    *
    * When ObjectPlace and ObjectSpawn packets are received from players, their objects lack mpNums,
    * so the server assigns them some based on incrementing the server's current mpNum, with the
    * operation's final mpNum becoming the server's new current mpNum.
    *
    * \return The mpNum.
    */
    static int GetCurrentMpNum() noexcept;

    /**
    * \brief Set the current (latest) mpNum generated by the server.
    *
    * When restarting a server, it is important to revert to the previous current (latest) mpNum
    * as stored in the server's data, so as to avoid starting over from 0 and ending up assigning
    * duplicate mpNums to objects.
    *
    * \param mpNum The number that should be used as the new current mpNum.
    * \return void
    */
    static void SetCurrentMpNum(int mpNum) noexcept;

    /**
    * \brief Get the plugin enforcement state of the server.
    *
    * If true, clients are required to use the same plugins as set for the server.
    *
    * \return The enforcement state.
    */
    static int GetPluginEnforcementState() noexcept;

    /**
    * \brief Set the plugin enforcement state of the server.
    *
    * If true, clients are required to use the same plugins as set for the server.
    *
    * \param state The new enforcement state.
    * \return void
    */
    static void SetPluginEnforcementState(bool state) noexcept;

    /**
    * \brief Write a log message with its own timestamp.
    *
    * It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
    *
    * \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
    *              3 for LOG_ERROR, 4 for LOG_FATAL).
    * \param message The message logged.
    * \return void
    */
    static void LogMessage(unsigned short level, const char *message) noexcept;

    /**
    * \brief Write a log message without its own timestamp.
    *
    * It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
    *
    * \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
    *              3 for LOG_ERROR, 4 for LOG_FATAL).
    * \param message The message logged.
    * \return void
    */
    static void LogAppend(unsigned short level, const char *message) noexcept;
};

#endif //OPENMW_MISCELLANEOUSAPI_HPP