/***************************************************************************
 *   Copyright (C) 2008 by SK Communications.                              *
 *   http://kldp.net/projects/nateon/                                      *
 *                                                                         *
 *   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 3 of the License, or     *
 *   (at your option) 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.             *
 ***************************************************************************/

#ifndef NATEONCONNECTION_H
#define NATEONCONNECTION_H

#include <qobject.h>
#include <qvaluelist.h>
#include <qptrqueue.h>
#include <qptrdict.h>
#include <qtimer.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include "knateonbuffer.h"

// forward declaration
class QMutex;
class MimeMessage;
class KExtendedSocket;
class CurrentAccount;
class KConfig;
class NOMHTTPProxy;

/**
   top most nateon connection class
   @author Doo-Hyun Jang <ring0320@nate.com>
*/
class NateonConnection :  public QObject
{
Q_OBJECT

public:
	// The constructor
	NateonConnection(QObject *parent = 0, const char *name = 0);
	NateonConnection(QString sIdentifier);

	// The destructor
	virtual ~NateonConnection();

	enum PROXYSTATE {PROXYCONNECTED, PROXYERROR, PROXYFAIL, PROXYHOSTCONNECTED};

	bool isConnected() const;
	const QString getUserID() const;
	const QString getLocalIP() const;
	int getTrid();
	int sendCommand(const QString& sPrefix, const QString& sText = "\r\n");
	void addCommand( int nTID, const QString& sPrefix, const QString& sText = "\r\n" );
	void sendCmd( const QString& sCommand );
	QTimer connectionTimer_;
	QTimer m_pingTimer;
	QTimer m_pRetryTimer;
	QPtrDict<QString> nextCommand;
    void parseMultiLine(  const QStringList& slCommand, const char *pData, Q_ULONG nDataLen );
	
protected:
	KConfig* config;
	
	void addPercents(QString &sWord) const;

	bool connectToServer(const QString& sServer, const int& nPort);
	void disconnectFromServer(bool isTransfer=false);

	unsigned int getBufferSize();
	QString getDataFromBuffer(const int& nLen);


	bool initialize();
	bool getSendPings() const;
	QString getValueFromMessage(const QString& sField, const QString& sMessage, bool goToEndOfLine = false) const;
	// const QString getLocalIp() const;
	QString getWord(const QString& sMessage, const int& nIndex) const;


	virtual bool parseCommand(const QStringList& slCommand) = 0;
	virtual bool parseMessage(const QString &sCommand, const QStringList& slCommand, const MimeMessage& message) = 0;
	virtual bool parseBuffer(const QStringList& slCommand, QString m_Buffer) = 0;

	virtual void proxyFailed();
	void removePercents(QString& sWord) const;

	int sendBinaryCommand(const QString& sPrefix, const QByteArray &sText);
	void setSendPings(bool   sendPings);

	///
	void sendCommand_noTid(const QString& sPrefix, const QString& sText = "\r\n");

	/// 로그인 사용자 정보
	CurrentAccount *m_pCurrentAccount;
	int m_nTrid;

private:

	bool connectToServerDirectly(const QString& sServer, const int& nPort);
	bool connectToServerViaProxy(const QString& sServer, const int& nPort);

	void resetPingTimer();
	void reconnectSocketSignal(bool hostconnected);
	void setProxyState(PROXYSTATE state);
	void socks5_auth(void);
	void socks5_connect(void);
	void socks5_reply(const char *szBuf, int nRead);

	void writeData(const QString& sData);
	void writeBinaryData(const QByteArray& data);
	void writeProxyData(const char *sBuf, int nLen);

	//QCString m_csBuffer;
	int m_nDestPort;
	QString m_sDestServer;
	QString m_sIdentifier;
	bool m_bInitialized;
	int m_nMissedPings;
	bool m_bSendPings;
	bool m_bPingReceived;

	KExtendedSocket *m_pSocket;

	QMutex *mproxywriteLocked_;
	int m_nProxyState;
	struct sockaddr_in m_addr_destServer;
	bool m_bWriteLocked;
	KNateonBuffer         m_Buffer;

	QPtrQueue<QString> qCommand;
	QString sConfirmCommand;
	QString sConfirmTID;
	bool bRunning;
	QTimer tCommandTimeout;
	NOMHTTPProxy *m_pHttpProxy;
    bool bMultiLine;
	
private slots:
	void dataReceived();
	void sendPing();
	void proxyConnected(void);
	void proxyDataReceived(void);
	virtual void socketError(int nError);
	void socketclosed(int nFlag);
	void slotConnectionTimeout();
	// A buffer where we save the data until a command is received complete
	void slotRetry();
	void slotRunCommand();
	
protected slots:
	virtual void connectionSuccess();
	void slotCommandTimeout();

signals:
	void disconnected();
	void statusMessage(QString sMessage, int connectStatus);
	void messageReceived(const QString &sMsg);
	void messageSent(const QString &sMsg);
	void pingError();
// 	void addQueue();

	//signals: // Public signals
};
#endif
