/*
 * This file is part of Danbooru Client.
 * Copyright 2013  Luca Beltrame <lbeltrame@kde.org>
 *
 * 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) version 3 or any later version
 * accepted by the membership of KDE e.V. (or its successor approved
 * by the membership of KDE e.V.), which shall act as a proxy
 * defined in Section 14 of version 3 of the license.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "danbooruconnectwidget.h"
#include "libdanbooru/danbooruservice.h"

#include <QCryptographicHash>
#include <QDebug>

#include <KWallet>

using KWallet::Wallet;

namespace Danbooru
{

const QMap< QUrl, QString > initBoardSalts()
{

    QMap< QUrl, QString > boardSalts;

    boardSalts.insert(QUrl("http://konachan.com"),
                      QString("So-I-Heard-You-Like-Mupkids-?--%1--"));
    boardSalts.insert(QUrl("http://konachan.net"),
                      QString("So-I-Heard-You-Like-Mupkids-?--%1--"));
    boardSalts.insert(QUrl("http://yande.re"),
                      QString("choujin-steiner--%1--"));
    boardSalts.insert(QUrl("http://danbooru.donmai.us"),
                      QString("choujin-steiner--%1--"));

    return boardSalts;
}

const QMap<QUrl, QString> DanbooruConnectWidget::boardSalts = initBoardSalts();

DanbooruConnectWidget::DanbooruConnectWidget(QVector< QUrl > urlList,
        QWidget *parent):
    QWidget(parent),
    m_wallet(0)

{
    setupUi(this);

    danbooruUrlComboBox->setFocus();
    closeButton->setIcon(QIcon::fromTheme(QLatin1String("dialog-close")));
    closeButton->setToolTip(i18n("Close dialog and discard changes"));
    userLineEdit->setClearButtonEnabled(true);
    passwdLineEdit->setClearButtonEnabled(true);
    passwdLineEdit->setEchoMode(QLineEdit::Password);

    if (anonCheckBox->isChecked()) {
        userLineEdit->setEnabled(false);
        passwdLineEdit->setEnabled(false);
    }

    danbooruUrlComboBox->clear();

    for (auto item : urlList) {
        danbooruUrlComboBox->insertUrl(urlList.indexOf(item), item);
    }

    m_wallet = Wallet::openWallet(Wallet::NetworkWallet(), 0,
                                  Wallet::Asynchronous
                                 );

    connect(m_wallet, &KWallet::Wallet::walletOpened, this, &DanbooruConnectWidget::checkWallet);

    connect(danbooruUrlComboBox, static_cast<void (KComboBox::*)(int)>(&KComboBox::currentIndexChanged), this, &DanbooruConnectWidget::getWalletData);

    connect(anonCheckBox, &QCheckBox::stateChanged, this, &DanbooruConnectWidget::toggleLineEdits);

    connect(buttonBox, &QDialogButtonBox::accepted, this, &DanbooruConnectWidget::accept);
    connect(closeButton, &QPushButton::clicked, [this]() {Q_EMIT(rejected());} );

}

DanbooruConnectWidget::~DanbooruConnectWidget()
{
    delete m_wallet;
}

void DanbooruConnectWidget::checkWallet(bool result)
{
    if (!result) {
        return;
    }

    if (!m_wallet->hasFolder(Wallet::PasswordFolder())) {
        m_wallet->createFolder(Wallet::PasswordFolder());
    }

    getWalletData();
}

void DanbooruConnectWidget::getWalletData()
{
    if (!m_wallet) {
        return;
    }

    QMap<QString, QString> valueMap;
    QString key = danbooruUrlComboBox->currentText();

    if (m_wallet->hasEntry(key)) {

        if (m_wallet->readMap(key, valueMap) != 0) {
            return;
        }

        m_username = valueMap[QLatin1String("username")];

        QString hashedPassword;

        // TODO: Handle the case where the "salt" is not known
        hashedPassword = boardSalts.value(key);

        hashedPassword = hashedPassword.arg(valueMap[QLatin1String("password")]);
        hashedPassword = QCryptographicHash::hash(hashedPassword.toUtf8(),
                         QCryptographicHash::Sha1).toHex();

        m_password = hashedPassword;
        userLineEdit->setText(m_username);
        passwdLineEdit->setText(valueMap[QLatin1String("password")]);

    }
}

void DanbooruConnectWidget::toggleLineEdits(int state)
{
    if (state == Qt::Unchecked) {
        userLineEdit->setEnabled(true);
        passwdLineEdit->setEnabled(true);
    } else if (state == Qt::Checked) {
        userLineEdit->setEnabled(false);
        passwdLineEdit->setEnabled(false);
    }
}

void DanbooruConnectWidget::setBoards(const QVector<QUrl> &urlList) {

    danbooruUrlComboBox->clear();

    for (auto item : urlList) {
        danbooruUrlComboBox->insertUrl(urlList.indexOf(item), item);
    }

}

QUrl DanbooruConnectWidget::boardUrl() const
{
    return m_boardUrl;
}

QString DanbooruConnectWidget::username() const
{
    return m_username;
}

QString DanbooruConnectWidget::password() const
{
    return m_password;
}

void DanbooruConnectWidget::accept()

{

    QString currentBoard = danbooruUrlComboBox->currentText();

    if (!userLineEdit->text().isEmpty() &&
        !passwdLineEdit->text().isEmpty() &&
        !anonCheckBox->isChecked()) {

        if (m_wallet && !m_wallet->hasEntry(currentBoard)) {
            QMap<QString, QString> dataMap;
            dataMap.insert(QLatin1String("username"), m_username);
            dataMap.insert(QLatin1String("password"), passwdLineEdit->text());
            m_wallet->writeMap(m_boardUrl.url(), dataMap);
        }

        // Only calculate if we haven't set a password from the wallet already
        if (m_password.isEmpty()) {

            QString hashedPassword = boardSalts.value(danbooruUrlComboBox->currentText());
            hashedPassword = hashedPassword.arg(currentBoard);
            hashedPassword = QCryptographicHash::hash(hashedPassword.toUtf8(),
                            QCryptographicHash::Sha1).toHex();
            m_password = hashedPassword;
        }
    }

    m_boardUrl = QUrl::fromUserInput(danbooruUrlComboBox->currentText());
    Q_EMIT(accepted());
}

bool DanbooruConnectWidget::isAnonymous() const {

    return anonCheckBox->isChecked();

}

} // namespace Danbooru
