/*
 *   This file is part of Dianara
 *   Copyright 2012-2019  JanKusanagi JRR <jancoding@gmx.com>
 *
 *   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.
 *
 *   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.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "downloadwidget.h"


DownloadWidget::DownloadWidget(QString fileUrl,
                               PumpController *pumpController,
                               QWidget *parent) : QFrame(parent)
{
    m_pumpController = pumpController;
    m_fileUrl = fileUrl;

    this->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
    m_downloading = false;
    m_aborted = false;


    QFont infoFont;
    infoFont.setPointSize(infoFont.pointSize() - 1);

    m_infoLabel = new QLabel(this);
    m_infoLabel->setAlignment(Qt::AlignCenter);
    m_infoLabel->setFont(infoFont);
    m_infoLabel->hide();


    m_openButton = new QPushButton(QIcon::fromTheme("document-open",
                                                    QIcon(":/images/button-open.png")),
                                   tr("Open",
                                      "Verb, as in: Open the downloaded file"),
                                   this);
    m_openButton->setFlat(true);
    m_openButton->hide();
    connect(m_openButton, &QAbstractButton::clicked,
            this, &DownloadWidget::openAttachment);


    m_downloadButton = new QPushButton(QIcon::fromTheme("download",
                                                        QIcon(":/images/button-download.png")),
                                       tr("Download"),
                                       this);
    m_downloadButton->setToolTip("<b></b>"
                                 + tr("Save the attached file to your folders"));
    m_downloadButton->setFlat(true);
    connect(m_downloadButton, &QAbstractButton::clicked,
            this, &DownloadWidget::downloadAttachment);


    m_progressBar = new QProgressBar(this);
    m_progressBar->setValue(0);
    m_progressBar->hide();       // Initially hidden


    m_cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                      QIcon(":/images/button-cancel.png")),
                                     tr("Cancel"),
                                     this);
    m_cancelButton->hide();
    connect(m_cancelButton, &QAbstractButton::clicked,
            this, &DownloadWidget::cancelDownload);


    m_layout = new QHBoxLayout();
    m_layout->addWidget(m_infoLabel);
    m_layout->addWidget(m_openButton);
    m_layout->addWidget(m_downloadButton);
    m_layout->addWidget(m_progressBar);
    m_layout->addWidget(m_cancelButton);
    this->setLayout(m_layout);

    qDebug() << "DownloadWidget created";
}

DownloadWidget::~DownloadWidget()
{
    qDebug() << "DownloadWidget destroyed";
}


void DownloadWidget::resetWidget()
{
    m_downloadButton->show();

    m_progressBar->hide();
    m_openButton->setToolTip(QString());
    m_openButton->hide();
    m_cancelButton->hide();

    m_networkReply->disconnect();
    m_networkReply->deleteLater();

    disconnect(m_pumpController, &PumpController::downloadCompleted,
               this, &DownloadWidget::completeDownload);
    disconnect(m_pumpController, &PumpController::downloadFailed,
               this, &DownloadWidget::onDownloadFailed);

    m_downloadedFile.close();

    m_downloading = false;
    m_aborted = false;
}


void DownloadWidget::updateSuggestedFilename(QString newFilename)
{
    m_suggestedFilename = newFilename;
}



////////////////////////////////////////////////////////////////////////////
////////////////////////////////// SLOTS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////


void DownloadWidget::downloadAttachment()
{
    if (m_downloading)
    {
        qDebug() << "Already downloading!!";
        return;
    }

    QString filename;
    filename = QFileDialog::getSaveFileName(this,
                                            tr("Save File As..."),
                                            QDir::homePath() + "/"
                                            + m_suggestedFilename,
                                            tr("All files") + " (*)");

    if (!filename.isEmpty())
    {
        m_downloading = true;

        m_infoLabel->setText(QStringLiteral("..."));
        m_infoLabel->setToolTip(QString());
        m_infoLabel->show();

        m_downloadButton->hide();
        m_openButton->hide();

        m_progressBar->show();
        m_progressBar->setValue(0);
        m_progressBar->setToolTip(QString());

        m_cancelButton->show();

        m_downloadedFile.setFileName(filename);
        m_downloadedFile.open(QIODevice::WriteOnly);

        m_networkReply = this->m_pumpController->getMedia(m_fileUrl);
        connect(m_networkReply, &QIODevice::readyRead,
                this, &DownloadWidget::storeFileData);
        connect(m_networkReply, &QNetworkReply::downloadProgress,
                this, &DownloadWidget::updateProgressBar);

        connect(m_pumpController, &PumpController::downloadCompleted,
                this, &DownloadWidget::completeDownload);
        connect(m_pumpController, &PumpController::downloadFailed,
                this, &DownloadWidget::onDownloadFailed);
    }
}


void DownloadWidget::openAttachment()
{
    /*
     * TODO: Open button could be visible from the start, and actually
     *       download the file to temporary storage before opening it.
     *       This would hide the Download button.
     *       When download completes, a new "Save" button would appear, to
     *       let the user save the temporary file to regular storage.
     */
    if (m_downloadedFile.exists())
    {
        QDesktopServices::openUrl(QUrl::fromLocalFile(m_downloadedFile.fileName()));
    }
    else
    {
        m_infoLabel->setText(tr("File not found!"));
        m_infoLabel->setToolTip(m_downloadedFile.fileName());

        m_openButton->hide();
        m_downloadButton->show(); // Chance to download again.
    }
}


void DownloadWidget::cancelDownload()
{
    int confirmation = QMessageBox::question(this, tr("Abort download?"),
                                             tr("Do you want to stop "
                                                "downloading the attached "
                                                "file?"),
                                             tr("&Yes, stop"),
                                             tr("&No, continue"),
                                             QString(), 1, 1);

    if (confirmation == 0)
    {
        m_aborted = true;
        m_networkReply->abort();

        const QString abortMessage = tr("Download aborted");
        m_infoLabel->setText(abortMessage);
        m_pumpController->showStatusMessageAndLogIt(abortMessage
                                                    + QStringLiteral("."));
        resetWidget();
    }
    else
    {
        qDebug() << "Confirmation cancelled, NOT stopping download";
    }
}


void DownloadWidget::completeDownload(QString url)
{
    if (url == m_fileUrl  // Ensure completed download is this download
     && !m_aborted)       // And wasn't aborted
    {
        m_infoLabel->setText(tr("Download completed"));
        resetWidget(); // This also closes the file

        // FIXME: pass this through GlobalObject
        m_pumpController->showStatusMessageAndLogIt(tr("Attachment downloaded "
                                                       "successfully to %1",
                                                       "%1 = filename")
                                                    .arg(m_downloadedFile.fileName()));

        m_openButton->setToolTip("<b></b>"
                                 + tr("Open the downloaded attachment with "
                                      "your system's default program for "
                                      "this type of file.")
                                 + "<br /><br />"
                                 + m_downloadedFile.fileName());
        m_openButton->show();
        m_downloadButton->hide();
    }
}


void DownloadWidget::onDownloadFailed(QString url)
{
    if (url == m_fileUrl) // Ensure failed download is this download
    {
        m_infoLabel->setText(tr("Download failed"));
        m_infoLabel->setToolTip(url);
        qDebug() << "Download FAILED!" << url;

        resetWidget();

        // FIXME: pass this through GlobalObject
        m_pumpController->showStatusMessageAndLogIt(tr("Downloading attachment "
                                                       "failed: %1",
                                                       "%1 = filename")
                                                    .arg(this->m_downloadedFile.fileName()),
                                                    url);
    }
}


void DownloadWidget::storeFileData()
{
    QByteArray data = m_networkReply->readAll();
    int httpStatus = m_networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute)
                                  .toInt();
    if (httpStatus == 200)
    {
        m_downloadedFile.write(data);
        qDebug() << "Storing data into:" << m_downloadedFile.fileName();
        qDebug() << data.length() << "bytes";
    }
    else
    {
        qDebug() << "Not storing data into:" << m_downloadedFile.fileName();
        qDebug() << "Because HTTP status code is:" << httpStatus;
    }
}


void DownloadWidget::updateProgressBar(qint64 received, qint64 total)
{
    m_progressBar->setRange(0, total);
    m_progressBar->setValue(received);

    m_infoLabel->setText(tr("Downloading %1 KiB...")
                         .arg(QLocale::system().toString(total / 1024)));

    QString downloadedTooltip = tr("%1 KiB downloaded")
                                .arg(QLocale::system().toString(received / 1024));
    m_infoLabel->setToolTip(downloadedTooltip);
    m_progressBar->setToolTip(downloadedTooltip);
}
