/*
 *      Code from:              Philipp Meinen
 *      Copyright (C):          2003-2004 Philipp Meinen
 *
 *      Email:                  lancelot@lancelot2k.dyndns.org
 *      Homepage:               http://lancelot2k.dyndns.org
 *      License:                GPL
 *                                                      */

#ifndef _SERVER_H_
#define _SERVER_H_ 1

#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#include "config.h"
#include "classes.h"
#include "functions.h"
#include "input_parameters.h"

class Server {
private:
	int connect_status;            /* the different status are defined in the file "config.h" */
	bool do_connect;               /* do we have to reconnect? 1 = yes; 0 = no */
	int cs_printed;                /* 1 = yes, we printed the connection status; 0 = no, we didnt print the connection status */
	pthread_t nameresolver;
	int socketfd;                  /* network socket - filedescriptor */
	int port;
	int maybe_reconnect;           /* if this is 1 and autoreconnect = 1 we have to reconnect ! */ 
	long last_ping;                /* time when we have sent the last PING */
	char InputData[INPUT_BUFFER_LEN];
	char OneInputLine[ONELINE_READ_MAXLEN];
	char servername[SERVER_NAME_LEN];
	char help_buffer[HELP_BUF_LEN];
	char normal_text[HELP_BUF_LEN];
	struct sockaddr_in socket_data;
	int StartCommandsSent;
	int LastCommandTime;
	int ModesSet;        /* have we sent your desired modes after connect ? */
	/* Parsing Variables */
	int parsing_finished;
	char ** InputParameters;
	int Num_InputParameters;
	/* end Parsing Variables */
	/* Parsefunctions */
	void ParseInput(void);
	void Read_InputParameters(void);
	void Cleanup_InputParameters(void);
	int Check_InputData(int atnum); /* ret: 1 = ok; 0 = false format */
	int Check_Parameter_for_space(int parameter_nr); /* ret: 0 = no space in this parameter; 1 = there are spaces in this Parameter */
	void Put_Text_together(int startposition);      /* concates textes from 'char ** InputParameters' to one string and stores this string in 'normal_text' */
	void ReadOneLineFromInput(void);
	int GetAnswerTypeNr(void);
	void Parsing_Finished(void);
	void ParseCommand_221(void);	/* RPL_UMODEIS  	"<user mode string>" */
	void ParseCommand_265(void);	/* Was not discribed in RFC documentation, in the freenode network it is a "Current local users" msg */
	void ParseCommand_266(void);	/* Was not discribed in RFC documentation, in the freenode network it is a "Current global users" msg */
	void ParseCommand_267(void);	/* Was not discribed in RFC documentation, in the gamesnet network it is a "Service agents online" msg */
	void ParseCommand_315(void);	/* RPL_ENDOFWHO  	"<name> :End of WHO list" */
	void ParseCommand_318(void);	/* RPL_ENDOFWHOIS  	"<nick> :End of WHOIS list" */
	void ParseCommand_324(void);	/* RPL_CHANNELMODEIS  	"<channel> <mode> <mode params>" */
	void ParseCommand_329(void);	/* not in rfc, but seems to be when a channel has been created -> "<channel> <unix-timestamp>"*/
	void ParseCommand_331(void);	/* RPL_NOTOPIC  	"<channel> :No topic is set" */
	void ParseCommand_332(void);	/* RPL_TOPIC		"<channel> :<topic> */
	void ParseCommand_333(void);	/* Was also not discribed in RFC documentation, in the freenode network it is a information about who has when set the topic of a channel => "<channel> <nickname> <unix-timestamp> */
	void ParseCommand_353(void);	/* RPL_NAMREPLY		"( "=" / "*" / "@" ) <channel>  :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )" */
	void ParseCommand_366(void);	/* RPL_ENDOFNAMES	"<channel> :End of NAMES list" */
	void ParseCommand_372(void);	/* RPL_MOTD		":- <text>" */
	void ParseCommand_375(void);	/* RPL_MOTDSTART	":- <server> Message of the day - " */
	void ParseCommand_376(void);	/* RPL_ENDOFMOTD	":End of MOTD command" */
	void ParseCommand_401(void);	/* ERR_NOSUCHNICK 	"<nickname> :No such nick/channel" */
	void ParseCommand_403(void);	/* ERR_NOSUCHCHANNEL 	"<channel name> :No such channel" */
	void ParseCommand_421(void);	/* ERR_UNKNOWNCOMMAND  	"<command> :Unknown command" */
	void ParseCommand_433(void);	/* ERR_NICKNAMEINUSE */
	void ParseCommand_451(void);	/* ERR_NOTREGISTERED */
	void ParseCommand_461(void);	/* ERR_NEEDMOREPARAMS  	"<command> :Not enough parameters" */
	void ParseCommand_473(void);	/* ERR_INVITEONLYCHAN  	"<channel> :Cannot join channel (+i)" */
	void ParseCommand_474(void);	/* ERR_BANNEDFROMCHAN  	"<channel> :Cannot join channel (+b)" */
	void ParseCommand_475(void);	/* ERR_BADCHANNELKEY  	"<channel> :Cannot join channel (+k)" */
	void ParseCommand_502(void);	/* ERR_USERSDONTMATCH 	":Cannot change mode for other users" */
	void ParseCommand_PONG(void);
	void ParseCommand_PRIVMSG(void); /* :nickname!~pcname@addr PRIVMSG #channel :text */
	void ParseCommand_NOTICE(void);
	void ParseCommand_JOIN(void);
	void ParseCommand_PART(void); /* :nickname!pcname@addr PART #channel :"leave-message" */
	void ParseCommand_QUIT(void); /* :nickname!pcname@addr QUIT :"leave-message" */
	void ParseCommand_NICK(void);
	void ParseCommand_MODE(void);
	void ParseCommand_KICK(void);
	void ParseCommand_TOPIC(void);
	void ParseCommand_PING(void);
	void ParseCommand_WALLOPS(void);
	void ParseCommand_SERVERNOTICE(void); /* "NOTICE <something> :*** <blabla text>" */
	void GetSenderName(char * Destination, int Source_Parameter, int max_dest_len);  /* makes ":nickname!~pcname@addr PRIVMSG #channel :text" to "nickname" */
	void GetChannelName(char * Destination, int Source_Parameter, int max_dest_len); /* this function makes ":nickname!~pcname@addr JOIN :#channel" or ":networkname msgtype Nickname #channel :#notthis" to "channel" */
	void TopicHandler(int type); /* type : 0 = command 332 ; 1 = command TOPIC */
	void PrintNormalText(char * nickname); /* ":server 001 nickname :Welcome blabla" will be printed as "'nickname'> Welcome blabla "*/
	void ResetParameters(void);
public:
	Server(void);
	~Server(void);
	void Connect(void);      /* ret: 0 = failed; 1 = OK     */
	void Disconnect(void);   /* ret: 0 = with error; 1 = OK */
	void GetHostname(void);
	int SetServername(char * new_servername); /* ret: 0 = to long; 1 = OK */
	int SetServerport(int new_port);      /* ret: 0 = out of range; 1 = OK */
	char * GetServername(void);
	int GetServerport(void);
	int GetInput(void); /* ret: 0 = read error; 1 = new data */
	int WriteMessageToServer(char * new_message); /* ret: 0 = error; 1 = OK */
	void LoginToServer(void);
	void PingServer(void);
	void PARTChannelorChat(char * user_input);
	void QUITIrc(char * user_input);
	void JOINChannel(char * channel_name);
	void DirectMSG(char * user_input);
	void MECommand(char * user_input);
	void TOPIC_Change(char * user_input);
	void NICK_Change(char * user_input);
	void CTCP_User(char * user_input);
	void Connect_to_Server(char * user_input);
	void DoStartupJobs(void);
	int GetConnectStatus(void);
	void SetConnectStatus(int new_status);
	int GetNetworkSocket(void); /* ret: -1 if there is no network socket or the network socket*/
	int GetMaybeReconnect(void);
	void UnsetMaybeReconnect(void);
	int GetDoConnect(void);
	void RestartConnect(void);
};

#endif
