#ifndef _KVI_IRCLINK_H_
#define _KVI_IRCLINK_H_
//
//   File : kvi_irclink.h
//   Creation date : Tue Jul 30 19:25:17 2002 GMT by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
//
//   This program is FREE software. You can redistribute it and/or
//   modify it under the terms of the GNU General Public License
//   as published by the Free Software Foundation; either version 2
//   of the License, or (at your opinion) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//


#include "kvi_settings.h"

#include <qobject.h>
#include "kvi_string.h"
#include "kvi_sockettype.h"
#include "kvi_time.h"
#include "kvi_list.h"


//class KviConsole;
class KviIrcServer;
class KviProxy;

class QTimer;
class QSocketNotifier;

typedef struct _KviIrcLinkMsgEntry
{
	char                         * data_ptr;
	int                            data_len;
	struct _KviIrcLinkMsgEntry   * next_ptr;
} KviIrcLinkMsgEntry;

class KviSSL;

class KviConsole;

class KVIRC_API KviIrcLinkMonitor
{
public:
	KviIrcLinkMonitor(KviConsole * c);
	virtual ~KviIrcLinkMonitor();
protected:
	KviConsole * m_pMyConsole;
public:
	// message is null terminated
	virtual void incomingMessage(const char * message){};
	// message is NOT null terminated! For proxy connections it might spit out binary data!
	virtual void outgoingMessage(const char * message,int len){};
	virtual void connectionInitiated(){};
	virtual void connectionTerminated(){};
	// The monitor MUST die here!
	virtual void die(){ delete this; };
};



class KVIRC_API KviIrcLink : public QObject
{
	Q_OBJECT
public:
	KviIrcLink(KviConsole * c,const char * name);
	~KviIrcLink();
public:
	enum LinkState { Ready , Connecting , ProxyLogin , Connected , ProxyFinalV4 ,
					ProxyFinalV5 , ProxySelectAuthMethodV5 , ProxyUserPassV5 ,
					ProxyFinalHttp , SSLHandshake };
	enum LinkEvent { Error , Warning , Message , StateChange , ProxyMessage ,
					ProxyError , SSLMessage , SSLError , SSLCertificate , SSLCipherInfo };
protected:
	unsigned int           m_uId;
	KviConsole           * m_pConsole;
	kvi_socket_t           m_sock;
	LinkState              m_state;
	QSocketNotifier      * m_pWsn;
	QSocketNotifier      * m_pRsn;
	KviIrcServer         * m_pIrcServer;
	KviProxy             * m_pProxy;
	QTimer               * m_pTimeoutTimer;
	char                 * m_pReadBuffer;
	unsigned int           m_uReadBufferLen;
	unsigned int           m_uReadBytes;
	unsigned int           m_uSentBytes;
	unsigned int           m_uReadPackets;
	unsigned int           m_uSentPackets;
	KviIrcLinkMsgEntry   * m_pSendQueueHead;
	KviIrcLinkMsgEntry   * m_pSendQueueTail;
	QTimer               * m_pFlushTimer;
	struct timeval         m_tAntiFloodLastMessageTime;
#ifdef COMPILE_SSL_SUPPORT
	KviSSL               * m_pSSL;
#endif
public:
	unsigned int id(){ return m_uId; };
	KviConsole * console(){ return m_pConsole; };
#ifdef COMPILE_SSL_SUPPORT
	bool usingSSL(){ return m_pSSL; };
#else
	bool usingSSL(){ return false; };
#endif
	unsigned int readBytes(){ return m_uReadBytes; };
	unsigned int sentBytes(){ return m_uSentBytes; };
	LinkState state(){ return m_state; };
	bool isConnected(){ return m_state == Connected; };
	bool isReady(){ return m_state == Ready; };
	int connectToHost(KviIrcServer * srv,KviProxy * prx = 0,const char * bindAddress = 0);
//	bool sendData(const char *buffer,int buflen = -1);
	bool sendRawData(const char *buffer,int buflen);
	bool sendData(const char *buffer,int buflen = -1);
	bool sendFmtData(const char *fmt,...);
//	bool sendFmtData(const char *fmt,...);
	void abortConnection(){ reset(); };
	bool getLocalHostIp(KviStr &szIp,bool bIpV6);
	virtual void die();
	void suicide();
protected slots:
	void connectionTimedOut();
	void writeNotifierFired(int);
	void readData(int);
	void readProxyData(int);
	void flushSendQueue();
	void doSSLHandshake(int);
protected:
	virtual void processData(char * buffer,int len);
	virtual void outgoingMessageNotifyMonitors(const char * data,int len);

#ifdef COMPILE_SSL_SUPPORT
	void raiseSSLError();
	void printSSLPeerCertificate();
	void printSSLCipherInfo();
#endif
	void connectionEstabilished();
	void proxyLoginHttp();
	void proxyLoginV4();
	void proxyLoginV5();
	void proxyAuthUserPassV5();
	void proxySendTargetDataV5();
	void proxyHandleV5AuthReply(unsigned char reply);
	void proxyHandleV5MethodReply(unsigned char reply);
	void proxyHandleV5FinalReply(unsigned char reply);
	void proxyHandleV4FinalReply(unsigned char reply);
	void proxyHandleHttpFinalReply(const char * buffer,int bufLen);
	void handleInvalidSocketRead(int readedLength);
	virtual void reset();
	void free_msgEntry(KviIrcLinkMsgEntry * e);
	KviIrcLinkMsgEntry * alloc_msgEntry(int len);
	bool queue_removeMessage();
	void queue_removeAllMessages();
	virtual void queue_insertMessage(KviIrcLinkMsgEntry *msg_ptr);
	virtual void setState(LinkState st);
//	int errorFromSystemError(int sysErr);
};

/*ed:

public:
	virtual void linkEvent(KviIrcLink::LinkEvent ev,void * arg);
protected:
	virtual void linkSuicideRequest(KviIrcLink * l);
};
*/
#endif //_KVI_IRCLINK_H_
