#include "http.h"

Http::Http():QTcpSocket()
{	
	_follow_moving = false;
}


void Http::setHost(const QString &host,quint16 port){
	_host = host;
	_port = port;
}

/// добавляет переменную куки.
void Http::addCookie(const QString &name,const QString &value){
	_cookies[name] = value;	
}

void Http::addHeaderVariable(const QString &name,const QString &value){
	_header_variables[name] = value;
}
void Http::removeHeaderVariable(const QString &name)
{
        _header_variables.remove(name);
}

QString Http::cookies(){
	QStringList slist;
	QMapIterator<QString,QString> i(_cookies);
	while(i.hasNext()){
		i.next();
		slist.push_back(QString("%1=%2").arg(i.key()).arg(i.value()));		
	}
	return slist.join(";");
}
/// создает заголовок
QByteArray Http::makeHeader(const QString &path,QString method){
	QString header;
	QUrl url;
	url.setHost(_host);
	url.setPath(path);
	QString qget = path;
	if(!_proxy_addr.isEmpty()){
		qget = QString("http://%1%2").arg(_host).arg(path);
	}
	header = QString("%1 %2 HTTP/1.0\r\n").arg(method).arg(qget);
	addHeaderVariable("Host",_host);
	QMapIterator<QString,QString> i(_header_variables);
	while(i.hasNext()){
		i.next();
		header += QString("%1: %2\r\n").arg(i.key()).arg(i.value());		
	}
	// подставновка кукисов
	if(_cookies.size())
		header += QString("Cookie: %1\r\n").arg(cookies());		
	
	header += "\r\n";
	
	return header.toUtf8();
}
/// отправить get запрос.
/// \param QByteArray &content - буффер, куда сохранится результат
QByteArray Http::get(const QString &path){
	QByteArray header = makeHeader(path,"GET");
	return processAnswer(sendQuery(header));
}

QByteArray Http::sendQuery(const QByteArray &header)
{
	
	QString x = QString::fromUtf8(header);
	
        QString host = _host;
	quint16 port = _port;
	if(!_proxy_addr.isEmpty()){
		host = _proxy_addr;
		port = _proxy_port;
	}
	connectToHost(host,port);
	if(!waitForConnected(30000)){
		qWarning() << "not connected";
		return QByteArray();
	}
	write(header);
	if(!waitForBytesWritten(2000)){
		qWarning() << "not writed";
		return QByteArray();
	}
	QByteArray answer;	
	while(waitForReadyRead(30000)){
		answer += readAll();	
	}
	disconnectFromHost();
	return answer;
}
QByteArray Http::processAnswer(const QByteArray &answer){
	QStringList slist;
	slist = QString(answer).split("\r\n\r\n");
	if(slist.size()==0){ 
                return QByteArray();
	}
	QString header = slist[0];
	if (slist.size()<2){
		return QByteArray();
	}
	_lastQueryResultCode = QString(header).left(12).right(3).toInt();	
	if(_lastQueryResultCode==302 && _follow_moving){
		return followMoving(header);// следовать перенаправлению.
        }
	QByteArray content = answer.right(answer.size()-header.size()-4);
	if(_lastQueryResultCode==100 && isUsingProxy()){
		return processAnswer(content);
	}
	splitCoockie(header.split("\r\n"));
	return content;
}

QString Http::headerParam(const QString &header, const QString name)
{
	QStringList lines = header.split("\n");
	foreach(QString line,lines){
		if(line.split(":").at(0)==name){
			return line.split(":").at(1).simplified();
		}		
	}
	return QString();
}

QByteArray Http::followMoving(const QString &header)
{
	removeHeaderVariable("Content-type");
	removeHeaderVariable("Content-Length");
	QString newurl = headerParam(header,"Location");
	return get(newurl);
}

void Http::splitCoockie(const QStringList &header){
	foreach(QString str,header){
		// разбор кукисов
		QRegExp rx("^Set-Cookie\\:(.*)$");
		if(rx.indexIn(str)!=-1){
			QString cstr = rx.cap(1);
			QStringList xlist = cstr.split(";");
			foreach(cstr,xlist){
				QStringList clist = cstr.split("=");
				if(clist.size()<2) continue;
				addCookie(clist[0].simplified(),clist[1].simplified());
			}
		}
	}
}

bool Http::isUsingProxy()
{
	return !_proxy_addr.isEmpty();
}

int Http::lastQueryResultCode()
{
	return _lastQueryResultCode;
}

QString Http::cookie(const QString &name)
{
	return _cookies[name];
}

void Http::setFollowMoving(bool f)
{
	_follow_moving = f;
}

//-----by Dealer_WeARE-----------
void Http::setProxyHostPort(QString host, int port,QString username, QString pass)
{
    _proxy_addr = host;
    _proxy_port = port;
    QNetworkProxy prx;
    prx.setPort(port);
    prx.setHostName(host);
    if(!username.isEmpty()) {
        prx.setUser(username);
        prx.setPassword(pass);
    }
    setProxy(prx);
}
