#ifndef SERVER_HPP
# define SERVER_HPP

# include <string>
# include <vector>
# include <map>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <poll.h>
# include <fcntl.h>
# include <unistd.h>
# include "ParseBuffer.hpp"
# include <iostream>
# include <stdexcept>
# include <cstring>
# include <csignal>
# include <cerrno>
# include "CommandValidator.hpp"
# include "Channel.hpp"
# include <cstdlib>

struct ConnectedUser
{
	int				fd;
	std::string		nick;
	std::string		username;
	std::string		realname;
	std::string		hostname;
	bool			passOk;
	bool			nickOk;
	bool			userOk;
	ParseBuffer		parseBuffer;

	ConnectedUser(void);
	explicit ConnectedUser(int fd);
	bool	isRegistered(void) const;
};

class Server
{
	private:
		int							_serverFd;
		int							_port;
		std::string					_password;
		std::vector<struct pollfd>		_fds;
		std::map<int, ConnectedUser>	_users;
		std::map<std::string, Channel>	_channels;

		void	acceptNew(void);
		void	handleRecv(int fd);
		void	removeUser(int fd);
		void	dispatch(int fd, const IrcMessage &msg);
		void	broadcastToChannel(const std::string &chanName, const std::string &msg, int exceptFd);

		void	handlePass(int fd, const IrcMessage &msg);
		void	handleNick(int fd, const IrcMessage &msg);
		void	handleUser(int fd, const IrcMessage &msg);
		void	handlePing(int fd, const IrcMessage &msg);
		void	handleQuit(int fd, const IrcMessage &msg);
		void	handleJoin(int fd, const IrcMessage &msg);
		void	handlePart(int fd, const IrcMessage &msg);
		void	handlePrivmsg(int fd, const IrcMessage &msg);
		void	handleKick(int fd, const IrcMessage &msg);
		void	handleInvite(int fd, const IrcMessage &msg);
		void	handleTopic(int fd, const IrcMessage &msg);
		void	handleMode(int fd, const IrcMessage &msg);

	public:
		Server(int port, const std::string &password);
		Server(const Server &other);
		Server	&operator=(const Server &other);
		~Server(void);

		void	start(void);
		void	run(void);
		void	sendReply(int fd, const std::string &msg);
};

#endif
