#ifndef CHANNEL_HPP_
#define CHANNEL_HPP_
#include "client.hpp"
#include <map>
#include <set>
#include <string>


class Client; // fwd
class Channel {
    private:
        Channel(const char* name, bool persistent, bool oper_only, bool ident_only);
        bool topic(const char*); ///< validates and sets #chantopic
        void remove(Client*); ///< removes from #clients and might delete itself when empty
        static void get_peers(const Client*, std::set<Client*>&); ///< gives all "visible" clients that share a channel

        static std::map<std::string, Channel*> channels;
        std::set<Client*> clients;

        const char* chantopic; ///< channel's topic (also always non-NULL)
        const bool persistent; ///< keep even when empty (predefined channel)
        const bool oper_only; ///< can only opers join?
        const bool ident_only; ///< need ident/voice/nickserv to join?

    public:
        const char* const name; ///< channel's name

        static Channel* getInst(const char* name, bool only_if_exists=false, bool persistent=false, bool oper_only=false, bool ident_only=false); ///< gets or creates channel
        static bool createInsts(); ///< creates all persistent channels stated by global config
        ~Channel(); ///< destroys empty channel
        static void killall(); ///< calls all ~Channel() upon shutdown

        static void disconnect(Client*, const char*); ///< broadcasts QUIT (with a reason) to all channels and remove() client
        static bool nickchange(const char*, Client*); ///< replies and broadcasts NICK-change to all shared channel-members
        static bool list(Client*); ///< replies with list of all channels
        static bool mode(Client*); ///< replies and broadcasts e.g. MODE +o
        static bool is_peer(const Client*, const Client*); ///< do they share a common channel (i.e. can 'see' each other)?

        bool join(Client*); ///< check, reply and broadcast join, welcome with topic and names
        bool part(Client*, const char*); ///< replies and broadcasts PART (with a reason), remove() client
        bool who(Client*); ///< replies with who list
        bool mode_get(Client*); ///< get channel modes
        bool privmsg(Client*, const char*); ///< send channel-wide message
        bool topic(Client*); ///< get topic
        bool topic(Client*, const char*); ///< set topic
        void cleanup(); ///< deletes channel if empty and permissive
};


#endif