/*
    authmanger.cpp

	Copyright (c) 2011 by Evgeny Khryukin

 ***************************************************************************
 *                                                                         *
 *   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 option) any later version.                                   *
 *                                                                         *
 ***************************************************************************
*/

#include <QNetworkReply>
#include <QTimer>
#include "authmanager.h"
#include "options.h"
#include "requestauthdialog.h"
#include "common.h"


AuthManager::AuthManager(QObject* p)
	: QObject(p)
	, authorized_(false)
{
	manager_ = newManager(this);
	connect(manager_, SIGNAL(finished(QNetworkReply*)), SLOT(replyFinished(QNetworkReply*)));

	timer_ = new QTimer(this);
	timer_->setInterval(10000);
	timer_->setSingleShot(true);
	connect(timer_, SIGNAL(timeout()), SLOT(timeout()));

	loop_ = new QEventLoop(this);
}

AuthManager::~AuthManager()
{
	if(timer_->isActive())
		timer_->stop();

	if(loop_->isRunning())
		loop_->exit();
}

bool AuthManager::go(const QString& login, const QString& pass, const QString& captcha)
{
	narodLogin = login;
	narodPass = pass;
	QString narodCaptchaKey = captcha;
	Options *o = Options::instance();

	QByteArray post = "login=" + narodLogin.toLatin1() + "&passwd=" + narodPass.toLatin1();
	if (narodLogin.isEmpty() || narodPass.isEmpty() || !narodCaptchaKey.isEmpty()) {
		requestAuthDialog authdialog;
		authdialog.setLogin(narodLogin);
		authdialog.setPasswd(narodPass);
		if (!narodCaptchaKey.isEmpty()) {
			authdialog.setCaptcha(manager_->cookieJar()->cookiesForUrl(mainUrl),
					      "http://passport.yandex.ru/digits?idkey=" + narodCaptchaKey);
		}
		if (authdialog.exec()) {
			narodLogin = authdialog.getLogin();
			narodPass = authdialog.getPasswd();
			if (authdialog.getRemember()) {
				o->setOption(CONST_LOGIN, narodLogin);
				o->setOption(CONST_PASS, Options::encodePassword(narodPass));
			}
			post = "login=" + narodLogin.toLatin1() + "&passwd=" + narodPass.toLatin1();
		}
		else {
			post.clear();
		}
		if (!post.isEmpty() && !narodCaptchaKey.isEmpty()) {
			post += "&idkey="+narodCaptchaKey.toLatin1()+"&code="+authdialog.getCode();
		}
	}
	if (!post.isEmpty()) {
		post += "&twoweeks=yes";
		QNetworkRequest nr = newRequest();
		nr.setUrl(authUrl);
		nr.setHeader(QNetworkRequest::ContentLengthHeader, post.length());
		nr.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
		manager_->post(nr, post);

		if(!loop_->isRunning()) {
			timer_->start();
			loop_->exec();
		}
	}
	else {
		return false;
	}

	return authorized_;
}

QList<QNetworkCookie> AuthManager::cookies() const
{
	QList<QNetworkCookie> ret;
	if(authorized_)
		ret = manager_->cookieJar()->cookiesForUrl(mainUrl);

	return ret;
}


void AuthManager::timeout()
{
	if(loop_->isRunning()) {
		authorized_ = false;
		loop_->exit();
	}
}

void AuthManager::replyFinished(QNetworkReply* reply)
{
	QVariant cooks = reply->header(QNetworkRequest::SetCookieHeader);
	if (!cooks.isNull()) {
		bool found = false;
		foreach (const QNetworkCookie& netcook, qVariantValue< QList<QNetworkCookie> >(cooks)) {
			if (netcook.name() == "yandex_login" && !netcook.value().isEmpty()) {
				found = true;
				break;
			}
		}
		if (!found) {
			QRegExp rx("<input type=\"?submit\"?[^>]+name=\"no\"");
			QString page = reply->readAll();
			if (rx.indexIn(page) > 0) {
				QRegExp rx1("<input type=\"hidden\" name=\"idkey\" value=\"(\\S+)\"[^>]*>");
				if (rx1.indexIn(page) > 0) {
					QByteArray post = "idkey=" + rx1.cap(1).toAscii() + "&filled=yes";
					QNetworkRequest nr = newRequest();
					nr.setUrl(authUrl);
					nr.setHeader(QNetworkRequest::ContentLengthHeader, post.length());
					nr.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
					manager_->post(nr, post);
					reply->deleteLater();
					return;
				}
			}
			else {
				rx.setPattern("<input type=\"hidden\" name=\"idkey\" value=\"(\\S+)\" />");
				if (rx.indexIn(page) > 0) {
					timer_->stop();
					go(narodLogin, narodPass, rx.cap(1));
					reply->deleteLater();
					return;
				}
				else {
					authorized_ = false;
					loop_->exit();
					reply->deleteLater();
					return;
				}
			}
		}
		else {
			authorized_ = true;
			loop_->exit();
			reply->deleteLater();
			return;
		}
	}

	authorized_ = false;
	loop_->exit();
	reply->deleteLater();
	return;
}
