/* Prototypes and external variable declarations.
 *
 * (C) 2003-2011 Anope Team
 * Contact us at team@anope.org
 *
 * Please read COPYING and README for further details.
 *
 * Based on the original code of Epona by Lara.
 * Based on the original code of Services by Andy Church.
 */

#ifndef EXTERN_H
#define EXTERN_H

#define E extern CoreExport
#define EI extern DllExport

#include "hashcomp.h"

E void ModuleRunTimeDirCleanUp();

/* IRC Variables */

E IRCDVar *ircd;
E IRCDProto *ircdproto;
E IRCdMessage *ircdmessage;

/**** actions.c ****/

E void kill_user(const Anope::string &source, User *user, const Anope::string &reason);
E bool bad_password(User *u);
E void common_unban(ChannelInfo *ci, User *u, bool full = false);

E BotInfo *BotServ;
E BotInfo *ChanServ;
E BotInfo *Global;
E BotInfo *HostServ;
E BotInfo *MemoServ;
E BotInfo *NickServ;
E BotInfo *OperServ;

/**** botserv.c ****/

E void get_botserv_stats(long *nrec, long *memuse);
E void bs_init();
E void botchanmsgs(User *u, ChannelInfo *ci, const Anope::string &buf);
E BotInfo *findbot(const Anope::string &nick);

/** Finds a pseudoclient, given a UID. Useful for TS6 protocol modules.
 * @param uid The UID to search for
 * @return The pseudoclient structure, or NULL if one could not be found
 */
E Anope::string normalizeBuffer(const Anope::string &);

E void check_ban(ChannelInfo *ci, User *u, int ttbtype);
E void bot_kick(ChannelInfo *ci, User *u, const char *message, ...);
E void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason);
E void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason);

/**** channels.c ****/

E void get_channel_stats(long *nrec, long *memuse);

E Channel *findchan(const Anope::string &chan);

E User *nc_on_chan(Channel *c, const NickCore *nc);

E Anope::string get_xop_level(int level);

E void do_cmode(const Anope::string &source, const Anope::string &channel, const Anope::string &modes, const Anope::string &ts);
E void do_join(const Anope::string &source, const Anope::string &channels, const Anope::string &ts);
E void do_kick(const Anope::string &source, const Anope::string &channel, const Anope::string &users, const Anope::string &reason);
E void do_part(const Anope::string &source, const Anope::string &channels, const Anope::string &reason);
E void MassChannelModes(BotInfo *bi, const Anope::string &modes);

E void chan_set_correct_modes(User *user, Channel *c, int give_modes);

inline BotInfo *whosends(ChannelInfo *ci)
{
	if (!ci || !ci->bi || !ci->c || !ci->botflags.HasFlag(BS_SYMBIOSIS) || !ci->c->FindUser(ci->bi))
		return ChanServ ? ChanServ : NickServ;
	return ci->bi;
}

/**** chanserv.c ****/

E LevelInfo levelinfo[];

E void get_chanserv_stats(long *nrec, long *memuse);

E void reset_levels(ChannelInfo *ci);
E void cs_init();
E void expire_chans();
E void cs_remove_nick(NickCore *nc);

E void check_modes(Channel *c);
E int check_valid_admin(User *user, Channel *chan, int servermode);
E int check_valid_op(User *user, Channel *chan, int servermode);

E ChannelInfo *cs_findchan(const Anope::string &chan);
E int check_access(User *user, ChannelInfo *ci, int what);
E bool IsFounder(User *user, ChannelInfo *ci);
E void update_cs_lastseen(User *user, ChannelInfo *ci);
E int get_idealban(ChannelInfo *ci, User *u, Anope::string &ret);

E int levelinfo_maxwidth;
E Anope::string get_mlock_modes(ChannelInfo *ci, int complete);

/**** config.c ****/

E ConfigurationFile services_conf;
E ServerConfig *Config;

/* hostserv.c */
E void do_on_id(User *u);
E void HostServSyncVhosts(NickAlias *na);

/**** encrypt.c ****/
E int enc_encrypt(const Anope::string &src, Anope::string &dest);
E int enc_decrypt(const Anope::string &src, Anope::string &dest);

/**** hostserv.c  ****/
E void get_hostserv_stats(long *nrec, long *memuse);
E void hostserv_init();

/**** init.c ****/

E void introduce_user(const Anope::string &user);
E bool GetCommandLineArgument(const Anope::string &name, char shortname = 0);
E bool GetCommandLineArgument(const Anope::string &name, char shortname, Anope::string &param);
E void Init(int ac, char **av);
E Uplink *uplink_server;

/**** ircd.c ****/
E void pmodule_ircd_proto(IRCDProto *);
E void pmodule_ircd_var(IRCDVar *ircdvar);
E void pmodule_ircd_message(IRCdMessage *message);

/**** language.cpp ****/
E std::vector<Anope::string> languages;
E void InitLanguages();
E const Anope::string GetString(NickCore *nc, const char *string);
E const Anope::string GetString(const Anope::string &domain, const Anope::string &lang, const char *string);
E void PushLanguage(const Anope::string &, Anope::string);
E void PopLanguage();
E const char *anope_gettext(const char *string);
E void SyntaxError(CommandSource &source, const Anope::string &command, const Anope::string &message);

/*** logger.cpp ***/
E void InitLogChannels(ServerConfig *);

/**** main.c ****/

E Anope::string services_dir;
E Anope::string services_bin;
E int debug;
E bool readonly;
E bool nofork;
E bool nothird;
E bool noexpire;
E bool protocoldebug;

E bool quitting;
E bool shutting_down;
E Anope::string quitmsg;
E bool save_data;
E time_t start_time;

E ConnectionSocket *UplinkSock;

E void save_databases();
E void expire_all();
E void sighandler(int signum);
E void do_restart_services();

/* The socket to our uplink */
class CoreExport UplinkSocket : public ConnectionSocket
{
 public:
	UplinkSocket(bool ipv6 = false);

	virtual ~UplinkSocket();

	bool Read(const Anope::string &buf);
};

/**** memoserv.c ****/

E void ms_init();
E void rsend_notify(CommandSource &source, Memo *m, const Anope::string &chan);
E void check_memos(User *u);
E MemoInfo *getmemoinfo(const Anope::string &name, bool &ischan, bool &isforbid);
E void memo_send(CommandSource &source, const Anope::string &name, const Anope::string &text, int z);

/**** messages.cpp ****/

E void init_core_messages();

E bool OnStats(const Anope::string &source, const std::vector<Anope::string> &);
E bool OnTime(const Anope::string &source, const std::vector<Anope::string> &);
E bool OnVersion(const Anope::string &source, const std::vector<Anope::string> &);

E bool On436(const Anope::string &, const std::vector<Anope::string> &);
E bool OnAway(const Anope::string &, const std::vector<Anope::string> &);
E bool OnJoin(const Anope::string &, const std::vector<Anope::string> &);
E bool OnKick(const Anope::string &, const std::vector<Anope::string> &);
E bool OnKill(const Anope::string &, const std::vector<Anope::string> &);
E bool OnMode(const Anope::string &, const std::vector<Anope::string> &);
E bool OnNick(const Anope::string &, const std::vector<Anope::string> &);
E bool OnUID(const Anope::string &, const std::vector<Anope::string> &);
E bool OnPart(const Anope::string &, const std::vector<Anope::string> &);
E bool OnPing(const Anope::string &, const std::vector<Anope::string> &);
E bool OnPrivmsg(const Anope::string &, const std::vector<Anope::string> &);
E bool OnQuit(const Anope::string &, const std::vector<Anope::string> &);
E bool OnServer(const Anope::string &, const std::vector<Anope::string> &);
E bool OnSQuit(const Anope::string &, const std::vector<Anope::string> &);
E bool OnTopic(const Anope::string &, const std::vector<Anope::string> &);
E bool OnWhois(const Anope::string &, const std::vector<Anope::string> &);
E bool OnCapab(const Anope::string &, const std::vector<Anope::string> &);
E bool OnSJoin(const Anope::string &, const std::vector<Anope::string> &);
E bool OnError(const Anope::string &, const std::vector<Anope::string> &);

/**** misc.c ****/

E bool IsFile(const Anope::string &filename);
E int toupper(char);
E int tolower(char);
#ifndef HAVE_STRLCPY
E size_t strlcpy(char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCAT
E size_t strlcat(char *, const char *, size_t);
#endif

E time_t dotime(const Anope::string &s);
E Anope::string duration(time_t seconds);
E Anope::string expire_left(NickCore *nc, time_t expires);
E Anope::string do_strftime(const time_t &t);
E bool doValidHost(const Anope::string &host, int type);

E bool isValidHost(const Anope::string &host, int type);
E bool isvalidchar(char c);

E Anope::string myStrGetToken(const Anope::string &str, char dilim, int token_number);
E Anope::string myStrGetTokenRemainder(const Anope::string &str, char dilim, int token_number);
E int myNumToken(const Anope::string &str, char dilim);
E void EnforceQlinedNick(const Anope::string &nick, const Anope::string &killer);
E bool nickIsServices(const Anope::string &nick, bool bot);

E void add_entropy_userkeys();
E void rand_init();
E unsigned char getrandom8();
E uint16 getrandom16();
E uint32 getrandom32();

E char *str_signed(unsigned char *str);

E std::list<Anope::string> BuildStringList(const Anope::string &, char = ' ');
E std::vector<Anope::string> BuildStringVector(const Anope::string &, char = ' ');

E bool str_is_wildcard(const Anope::string &str);
E bool str_is_pure_wildcard(const Anope::string &str);

/**** modes.cpp ****/
/* Number of generic modes we support */
E unsigned GenericChannelModes, GenericUserModes;
E std::multimap<ChannelModeName, ModeLock> def_mode_locks;
E void SetDefaultMLock(ServerConfig *config);

/**** nickserv.c ****/

E void get_aliases_stats(long &count, long &mem);
E void get_core_stats(long &count, long &mem);
E void change_core_display(NickCore *nc);
E void change_core_display(NickCore *nc, const Anope::string &newdisplay);
E int do_setmodes(User *u);

E void ns_init();
E int validate_user(User *u);
E void expire_nicks();
E NickAlias *findnick(const Anope::string &nick);
E NickCore *findcore(const Anope::string &nick);
E bool is_on_access(const User *u, const NickCore *nc);

/**** process.c ****/

E void process(const Anope::string &buf);

/**** send.c ****/

E void send_cmd(const Anope::string &source, const char *fmt, ...) FORMAT(printf, 2, 3);

E void notice_server(const Anope::string &source, const Server *s, const char *fmt, ...) FORMAT(printf, 3, 4);

/**** sessions.c ****/

E std::vector<Exception *> exceptions;

E void get_session_stats(long &count, long &mem);
E void get_exception_stats(long &count, long &mem);

E void add_session(User *u);
E void del_session(User *u);

E void expire_exceptions();

E Session *findsession(const Anope::string &host);

E Exception *find_host_exception(const Anope::string &host);
E Exception *find_hostip_exception(const Anope::string &host, const Anope::string &hostip);
E int exception_add(User *u, const Anope::string &mask, unsigned limit, const Anope::string &reason, const Anope::string &who, time_t expires);

/**** sockets.cpp ****/

E SocketEngineBase *SocketEngine;
E int32 TotalRead;
E int32 TotalWritten;
E SocketIO normalSocketIO;

/**** users.c ****/

E int32 opcnt;
E uint32 maxusercnt, usercnt;
E time_t maxusertime;

E void get_user_stats(long &count, long &mem);

E User *finduser(const Anope::string &nick);

E User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, const Anope::string &ip, const Anope::string &vhost, const Anope::string &uid, const Anope::string &modes);

E void do_umode(const Anope::string &user, const Anope::string &modes);
E void do_kill(User *user, const Anope::string &reason);

E bool matches_list(Channel *c, User *user, ChannelModeName mode);
E bool is_excepted_mask(ChannelInfo *ci, const Anope::string &mask);

E Anope::string create_mask(User *u);

/******************************************************************************/

E void b64_encode(const Anope::string &src, Anope::string &target);
E void b64_decode(const Anope::string &src, Anope::string &target);

#ifdef _WIN32
E Anope::string GetWindowsVersion();
E bool SupportedWindowsVersion();
#endif

#endif /* EXTERN_H */
