/***************************************************************************
 *   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.             *
 ***************************************************************************/

#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>

#include <krun.h>
#include <qfile.h>
#include <qdir.h>
#include <qobject.h>
#include <qstringlist.h>
#include <kdebug.h>
#include <qurloperator.h>
#include <qnetwork.h>
#include <qregexp.h>

#include "common.h"
#include "emoticon.h"
#include "utils.h"

extern nmconfig stConfig;

#if 0
#include <soundserver.h>
#include <artsc.h>
#include <artsc_export.h>
#include <kartsdispatcher.h>
#endif
Common::Common(QObject *parent, const char *name)
	: QObject(parent, name)
{
}


Common::~Common()
{
}


#include "common.moc"


/// 참고 : http://kldp.org/node/653
#define BUFFERSIZE 1024
QStringList Common::getLocalIP()
{
	const char* localip = "0.0.0.0";
	const int MAX_NIC = 10;
	struct ifconf ifc;
	struct ifreq ifr[MAX_NIC];
	QStringList slIP;

	int s;
	int nNumIFs;
	int i;
	int count;
	int max=2;
	static char ip[BUFFERSIZE];
	int cmd = SIOCGIFCONF;

	max++;

	ifc.ifc_len = sizeof ifr;
	ifc.ifc_ifcu.ifcu_req = ifr;

	if( (s=socket(AF_INET,SOCK_STREAM,0)) < 0)
	{
#ifdef NETDEBUG
		kdDebug() << "socket error!" << endl;
#endif
		return slIP;
	}

	if( ioctl(s, cmd, &ifc) < 0)
	{
#ifdef NETDEBUG
		kdDebug() << "ioctl error!" << endl;
#endif
		return slIP;
	}
	close(s);

	nNumIFs = ifc.ifc_len / sizeof ( struct ifreq );
	count = 0;
	strcpy( ip, localip );
	for( i=0; i<nNumIFs; i++ )
	{
		struct in_addr addr;
		if( ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr.sa_family != AF_INET)
		{
			continue;
		}

		addr = ((struct sockaddr_in *) & ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr)->sin_addr;
		if( addr.s_addr == htonl( 0x7f000001 ) )
		{
			continue;
		}
		strcpy( ip, inet_ntoa( addr ) );

		slIP.append( QString(ip) );
	}
	return slIP;
}

InviteWeb::InviteWeb(QObject *parent, const char *name)
	: QObject(parent, name),
	  http(0)
{
	http = new QHttp(this);
	connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(httpRequestFinished(int, bool)));
	// connect(http, SIGNAL(dataReadProgress ( int , int )), this, SLOT( slotReceivedData( int, int )));
	connect(http, SIGNAL( readyRead ( const QHttpResponseHeader& )), this, SLOT( slotReceivedData ( const QHttpResponseHeader & )));
}


InviteWeb::~InviteWeb()
{
}


void InviteWeb::httpRequestFinished(int id, bool error)
{
	if(id != httpId)
		return; // wasn't the most recent http request, so ignore it
	Q_UNUSED( error );
}

/*
  knateon: Web Query : [http://203.226.253.126/exipml35/get_invite_msg.jsp?cmn=902126197&ticket=E82501FE2B373132EEAE19F55A7C07016D548E733048956A601717A18732267FB1C8551E8E10701BD060CBCBAED7CCA24B78C144BB82799C2C89F7A8686319ED17A2F67B0CD23A623DB77600E1D9DEEC2427A51661D4AAB3E3F066B6387BC907F5348DA1B9956BCC3508074D80F09C144545E350FF4A64929602AFEE031E4F79F8332A64A56CE6555C2EF24149ABA327C918441EBBFA43D6]
*/
int InviteWeb::doResultFromCMN(QString sCMN, QString sTicket)
{
	QString host = "203.226.253.126";
	QString page("/exipml35/get_invite_msg.jsp?cmn=");
	page += sCMN;
	page += "&ticket=";
	page += sTicket;

	QHttpRequestHeader header( "GET", page );
	header.setValue( "Host", host );
	header.setValue( "Accept-Charset", "UTF-8");
	http->setHost(host);
	httpId = http->request( header );
	// httpId = http->get(page);
#ifdef NETDEBUG
	kdDebug() << "HTTP: [" << page << "]" << endl;
#endif
	return httpId;
}

void InviteWeb::slotReceivedData(const QHttpResponseHeader & qResponse)
{
	unsigned long ulsize = http-> bytesAvailable ();
	char *data;
	data = (char*)malloc(ulsize);
	memset(data, 0x00, ulsize);
  
	/* unsigned long rsize = */ http->readBlock ( data, ulsize);

	QString sData = QString::fromUtf8(data);

	QStringList slCommand = QStringList::split('\n', sData );
	if (slCommand[0].stripWhiteSpace() == "100 OK")
	{
		emit gotDataFromURL( slCommand );
	}
	Q_UNUSED( qResponse );
}


PostCGI::PostCGI( QObject * parent, const char * name )
: QObject( parent, name ),
http(0)
{
	http = new QHttp(this);
	connect( http, SIGNAL( readyRead( const QHttpResponseHeader& ) ), SLOT( slotReadAll( const QHttpResponseHeader& ) ) );
}

PostCGI::~ PostCGI()
{
}

int PostCGI::start( QString sURL, QString sParam )
{
#ifdef NETDEBUG
	kdDebug() << ">>>> HTTP URL : [" << sURL << "]" << endl;
#endif
	QUrl url( sURL );
#ifdef NETDEBUG
	kdDebug() << ">>>> HTTP URL : [" << url.host() << "]" << endl;
#endif

	QHttpRequestHeader header( "POST", sURL );
	QByteArray content = sParam.utf8();
	header.setValue( "Host", url.host() );
	header.setValue( "Accept-Charset", "UTF-8");
	header.setContentType("application/x-www-form-urlencoded");
	http->setHost( url.host() );
	httpId = http->request( header, content );
	return httpId;
}

void PostCGI::slotReadAll(const QHttpResponseHeader & resp)
{
	Q_UNUSED( resp );
	emit gotResult( http->readAll() );
}


/*!
  URL로 값을 받는 클레스
*/
WebCGI::WebCGI(QObject * parent, const char * name)
: QObject(parent, name),
http(0),
sFullData(0)
{
	http = new QHttp(this);
	connect(http, SIGNAL(requestFinished(int, bool)), SLOT(httpRequestFinished(int, bool)));
	connect(http, SIGNAL( readyRead ( const QHttpResponseHeader& )), SLOT( slotReceivedData ( const QHttpResponseHeader & )));
	connect(http, SIGNAL( done( bool ) ), SLOT( slotClose( bool ) ) );
}

WebCGI::~ WebCGI()
{
}

int WebCGI::start(QString sURL)
{
#ifdef NETDEBUG
	kdDebug() << ">>>> HTTP URL : [" << sURL << "]" << endl;
#endif
	QUrl url( sURL );
#ifdef NETDEBUG
	kdDebug() << ">>>> HTTP URL : [" << url.host() << "]" << endl;
#endif
	QHttpRequestHeader header( "GET", sURL );
	header.setValue( "Host", url.host() );
	header.setValue( "Accept-Charset", "UTF-8");
	http->setHost( url.host() );
	httpId = http->request( header );

	return httpId;
}

void WebCGI::httpRequestFinished(int id, bool error)
{
	if(id != httpId)
		return; // wasn't the most recent http request, so ignore it

	QStringList slCommand = QStringList::split('\n', QString::fromUtf8( sFullData ) );
	emit gotResult( slCommand );
	
	Q_UNUSED( error );
}

void WebCGI::slotReceivedData(const QHttpResponseHeader & qResponse)
{
	if ( http->currentId () != httpId )
		return;

	unsigned long ulsize = http-> bytesAvailable ();
	char *data;
	data = (char*)malloc(ulsize);
	memset(data, 0x00, ulsize);
	unsigned long rsize = http->readBlock ( data, ulsize);
	sFullData.add(data, rsize);
	
	Q_UNUSED( qResponse );
}

void WebCGI::slotClose(bool bErr)
{
	if ( http->currentId () != httpId )
		return;

#ifdef NETDEBUG
	if ( bErr )
	{
		kdDebug() << "WebCGI done() Error!" << endl;
	}
#endif
	http->closeConnection();
	
	Q_UNUSED( bErr );
}


#if 0
void Common::playsound(QString sFile)
{
	KArtsDispatcher dispatcher;
  
	Arts::SimpleSoundServer server = Arts::Reference("global:Arts_SimpleSoundServer");
	server.play( sFile );
}
#endif


QString Common::qEllipsisText(const QString & org, const QFontMetrics & fm, int width, int align)
{
	if (fm.width(org) <= width)
		return org;
  
	int ellWidth = fm.width( "..." );
	QString text = QString::fromLatin1("");
	int i = 0;
	int len = org.length();
	int offset = (align & Qt::AlignRight) ? (len-1) - i : i;
	while ( i < len && fm.width( text + org[ offset ] ) + ellWidth < width ) {
		if ( align & Qt::AlignRight )
			text.prepend( org[ offset ] );
		else
			text += org[ offset ];
		offset = (align & Qt::AlignRight) ? (len-1) - ++i : ++i;
	}
	if ( text.isEmpty() )
		text = ( align & Qt::AlignRight ) ? org.right( 1 ) : text = org.left( 1 );
	if ( align & Qt::AlignRight )
		text.prepend( "..." );
	else
		text += "...";
	return text;
}


static QAsciiDict<char> dPercents;

void loadPercent()
{
	dPercents.clear();
	dPercents.insert( "%20", " " );
	dPercents.insert( "%0D", "\r" );
	dPercents.insert( "%0A", "\n" );
	dPercents.insert( "%20", " " );
	dPercents.insert( "%21", "!" );
	dPercents.insert( "%22", "\"" );
	dPercents.insert( "%23", "#" );
	dPercents.insert( "%24", "$" );
	dPercents.insert( "%25", "%" );
	dPercents.insert( "%26", "&" );
	dPercents.insert( "%27", "'" );
	dPercents.insert( "%28", "(" );
	dPercents.insert( "%29", ")" );
	dPercents.insert( "%2A", "*" );
	dPercents.insert( "%2B", "+" );
	dPercents.insert( "%2C", "," );
	dPercents.insert( "%2D", "-" );
	dPercents.insert( "%2E", "." );
	dPercents.insert( "%2F", "/" );
	dPercents.insert( "%30", "0" );
	dPercents.insert( "%31", "1" );
	dPercents.insert( "%32", "2" );
	dPercents.insert( "%33", "3" );
	dPercents.insert( "%34", "4" );
	dPercents.insert( "%35", "5" );
	dPercents.insert( "%36", "6" );
	dPercents.insert( "%37", "7" );
	dPercents.insert( "%38", "8" );
	dPercents.insert( "%39", "9" );
	dPercents.insert( "%3A", ":" );
	dPercents.insert( "%3B", ";" );
	dPercents.insert( "%3C", "<" );
	dPercents.insert( "%3D", "=" );
	dPercents.insert( "%3E", ">" );
	dPercents.insert( "%3F", "?" );
	dPercents.insert( "%40", "@" );
	dPercents.insert( "%41", "A" );
	dPercents.insert( "%42", "B" );
	dPercents.insert( "%43", "C" );
	dPercents.insert( "%44", "D" );
	dPercents.insert( "%45", "E" );
	dPercents.insert( "%46", "F" );
	dPercents.insert( "%47", "G" );
	dPercents.insert( "%48", "H" );
	dPercents.insert( "%49", "I" );
	dPercents.insert( "%4A", "J" );
	dPercents.insert( "%4B", "K" );
	dPercents.insert( "%4C", "L" );
	dPercents.insert( "%4D", "M" );
	dPercents.insert( "%4E", "N" );
	dPercents.insert( "%4F", "O" );
	dPercents.insert( "%50", "P" );
	dPercents.insert( "%51", "Q" );
	dPercents.insert( "%52", "R" );
	dPercents.insert( "%53", "S" );
	dPercents.insert( "%54", "T" );
	dPercents.insert( "%55", "U" );
	dPercents.insert( "%56", "V" );
	dPercents.insert( "%57", "W" );
	dPercents.insert( "%58", "X" );
	dPercents.insert( "%59", "Y" );
	dPercents.insert( "%5A", "Z" );
	dPercents.insert( "%5B", "[" );
	dPercents.insert( "%5C", "\\" );
	dPercents.insert( "%5D", "]" );
	dPercents.insert( "%5E", "^" );
	dPercents.insert( "%5F", "_" );
	dPercents.insert( "%60", "`" );
	dPercents.insert( "%61", "a" );
	dPercents.insert( "%62", "b" );
	dPercents.insert( "%63", "c" );
	dPercents.insert( "%64", "d" );
	dPercents.insert( "%65", "e" );
	dPercents.insert( "%66", "f" );
	dPercents.insert( "%67", "g" );
	dPercents.insert( "%68", "h" );
	dPercents.insert( "%69", "i" );
	dPercents.insert( "%6A", "j" );
	dPercents.insert( "%6B", "k" );
	dPercents.insert( "%6C", "l" );
	dPercents.insert( "%6D", "m" );
	dPercents.insert( "%6E", "n" );
	dPercents.insert( "%6F", "o" );
	dPercents.insert( "%70", "p" );
	dPercents.insert( "%71", "q" );
	dPercents.insert( "%72", "r" );
	dPercents.insert( "%73", "s" );
	dPercents.insert( "%74", "t" );
	dPercents.insert( "%75", "u" );
	dPercents.insert( "%76", "v" );
	dPercents.insert( "%77", "w" );
	dPercents.insert( "%78", "X" );
	dPercents.insert( "%79", "y" );
	dPercents.insert( "%7A", "z" );
	dPercents.insert( "%7B", "{" );
	dPercents.insert( "%7C", "|" );
	dPercents.insert( "%7D", "}" );
	dPercents.insert( "%7E", "~" );
}


void Common::fixOutString(QString & sString)
{
	if ( dPercents.isEmpty() )
	{
#ifdef NETDEBUG
		kdDebug() << "loadPercent()" << endl;
#endif
		loadPercent();
	}
	/*!
	 * TODO: while string find %XX
	 * 구현해야 함.
	 */
	int nLen = sString.length();
	QString sNewString;
	for(int i=0; i<nLen; i++) {
		if (  sString[i] == '%' ) {
			if ( dPercents.find( sString.mid(i,3) ) ) {
				sNewString.append( dPercents[ sString.mid(i,3) ] );
				i += 2;
				continue;
			}
		}
		sNewString.append( sString[i] );
	}
	
#ifdef NETDEBUG
	kdDebug() << "Orig : [" << sString << "]" << endl;
	kdDebug() << "Modf : [" << sNewString << "]" << endl;
#endif
	
	sString = sNewString;
	
	Emoticon *pEmoticon	= Emoticon::instance();
	pEmoticon->replaseEmoticons( sString );
	
	return;
}


void Common::removePercents(QString & sWord)
{
	// Q_UNUSED( sWord );
	if ( dPercents.isEmpty() )
	{
#ifdef NETDEBUG
		kdDebug() << "XXXXXXXXXXXXXXX" << endl;
#endif
		loadPercent();
	}

	int nLen = sWord.length();
	QString sNewString;
	for(int i=0; i<nLen; i++) {
		if ( ( sWord[i] == '%' ) &&
		     ( sWord[i+1].isNumber() ) &&
		     ( sWord[i+2].isNumber() )
		   ) {
			   if ( dPercents.find( sWord.mid(i,3) ) ) {
				   sNewString.append( dPercents[ sWord.mid(i,3) ] );
				   i += 3;
			   }
		   }
		sNewString.append( sWord[i] );
	}
	
#ifdef NETDEBUG
	kdDebug() << "Orig : " << sWord << endl;
	kdDebug() << "Modf : " << sNewString << endl;
#endif
	
	sWord = sNewString;
	
#if 0
	QStringList slPercents;
	QRegExp rx("%[0-9A-F][0-9A-F]");
	int pos = 0;
	while ( pos >= 0 ) {
		pos = rx.search( sWord, pos );
		if ( pos > -1 ) {
#ifdef NETDEBUG
			kdDebug() << "REGEXP [" << rx.cap(0) << "]" << endl;
#endif
			if ( dPercents.find( rx.cap(0) ) )
				slPercents.append( rx.cap(0) );
				// sWord.replace( pos, rx.matchedLength(), dPercents[rx.cap(0)]);
			// pos++;
			pos += rx.matchedLength();
		}
	}
	
	for ( QStringList::Iterator it = slPercents.begin(); it != slPercents.end(); ++it ) {
		sWord.replace( *it, dPercents[*it] );
	}
#endif
}

void Common::nateLog(const QString & sLog)
{
	kdDebug() << sLog << endl;
	QFile file( QDir::homeDirPath() + "/file.txt" );
}

void Common::openWeb(const QString & sWeb)
{
	if ( ( stConfig.defaultwebbrowser ).length() > 0 )
	{
		QString sCommand;
		sCommand = stConfig.defaultwebbrowser;
		sCommand += " ";
		sCommand += "'";
		sCommand += sWeb;
		sCommand += "'";
		kdDebug() << sCommand << endl;
		system( sCommand.data() );
		return;
	}
}



void Common::percent2HTML(QString & sWord)
{
	sWord.replace("<", "&lt;");
	sWord.replace(">", "&gt;");
	sWord.replace("%0D", "<br>");
	sWord.replace("%0A", "");
	sWord.replace("%20", " ");
	sWord.replace("%25", "%");
}
