RaM Fire Updated/
/*
 * RAM $Id: ban.h 81 2009-01-14 06:16:31Z ghasatta $
 */

#include <vector>

#ifndef BAN__H
#define BAN__H

#define BAN_FILE            SYS_DIR "/ban.txt"
#define BAN_FILE_NEW        SYS_DIR "/ban_newfmt.txt"

typedef struct ban_data BAN_DATA;

/*
 * Site ban structure.
 */
#define BAN_SUFFIX               A
#define BAN_PREFIX               B
#define BAN_NEWBIES              C
#define BAN_ALL                  D
#define BAN_PERMIT               E
#define BAN_PERMANENT            F

/**
 * ban_manager is a singleton class that handles all ban functions, including data
 * management, disk i/o, and an API for matching bans.
 *
 * It is accessed as so: ban_manager::Instance()->add_ban(...)
 */
class ban_manager
{
public:
    /**
     * @brief Singleton accessor method - this is the only way to get at this class' member functions. This ensures that there is only
     * one copy of ban_manager invoked.
     */
    static ban_manager *Instance();

private:
    static ban_manager *pInstance;
    
    ban_manager();
    ~ban_manager();

public:
    /**
     * @brief Handles "ban" command input. Adds a ban.
     */
    static void do_ban(CHAR_DATA *ch, const char *argument);

    /**
     * @brief Obsolete command, instructs char to use 'ban' command, and exits.
     */
    static void do_permban(CHAR_DATA *ch, const char *argument);

    /**
     * @brief Handles "allow" command. Remove a ban, if it exists.
     */
    static void do_allow(CHAR_DATA *ch, const char *argument);
    
    /**
     * @brief Adds a ban, provided that a higher-level ban does not already exist for _name.
     *
     * @return Returns true if _level is sufficient to remove any existing bans for _name (or if there are no existing bans for _name).
     *
     * @param _level The trust level of the character attempting to add the ban.
     * @param _name The name of the ban, which can contain * wildcards.
     * @param _type The ban type - BAN_ALL, BAN_NEWBIES, or BAN_PERMIT
     * @param _perm If true, this ban is permanent and will be saved to disk.
     */
    bool add_ban(int _level, std::string _name, int _type, bool _perm);

    /**
     * @brief Removes a ban, provided that _level is sufficient to remove it.
     *
     * @return Returns true if _level is sufficient to remove the ban, or if no ban is found for _name.
     *
     * @param _level The trust level of the character attempting to remove the ban.
     * @param _name The name of the ban to be removed.
     * @param should_save Should save_bans() be called after removing the ban? Defaults to true
     */
    bool remove_ban(int _level, std::string _name, bool should_save = true);

    /**
     * @brief Saves entire list of bans in one file. Overwrites existing ban file with new bans.
     */
    void save_bans() const;

    /**
     * @brief Load all bans from file.
     */
    void load_bans();

    /**
     * @brief Returns true if a ban can be found that matches the name and type supplied.
     */
    bool is_banned(std::string _name, int _type) const;

    /**
     * @brief Get a formatted list of all current bans, ready to be printed to a character or log file.
     */
    std::string print_bans() const;
    
private:

    /**
     * @brief Bridge function to load old format ban file and immediately save new file.
     *
     * @return Returns true if old format file was found and operated on. False if not.
     */ 
    bool load_old_format();
    
    struct ban_data
    {
	ban_data(int _level, std::string _name, int flags);
	ban_data(int _level, std::string _name, int _type, bool _perm);
	~ban_data();

	/**
	 * @brief Does this ban match the supplied paramters?
	 *
	 * @param _name name to match
	 * @param exact_match Should we look for an exact match only?
	 *
	 * @return Returns true if match, false if not.
	 */
	bool is_match(std::string _name, bool exact_match) const;

	/**
	 * @brief Write this ban's data to the ofstream for saving.
	 */
	void write_save(std::ofstream &out) const;
	
	/**
	 * @brief Parses the name to decide if the ban name contains wildcards.
	 *
	 * @post this->ban_flags modified to set BAN_PREFIX and/or BAN_SUFFIX if necessary.
	 */
	void parse_name();

	int                     ban_flags;
	int                     level;
	std::string             name;
    };

    std::vector<ban_data> bans;

    /**
     * @brief Returns the ban requested, if found, or bans.end() if not. Volatile function version.
     */
    std::vector<ban_data>::iterator find_ban(std::string _name, bool exact_match = false);

    /*
     * @brief Returns the ban requested, if found, or bans.end() if not. Const function version.
     */
    std::vector<ban_data>::const_iterator find_ban(std::string _name, bool exact_match = false) const;
};

#endif