/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * A web viewer with more features.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgwebview.h"

#include <qprinter.h>
#include <qprintdialog.h>
#include <qclipboard.h>
#include <qpointer.h>
#include <qevent.h>
#include <qprintpreviewdialog.h>
#include <qapplication.h>
#include <qdesktopservices.h>
#include <qtextdocumentwriter.h>
#include <qtextdocument.h>
#include <qwebframe.h>
#include <qfileinfo.h>
#include <qmath.h>

#include <qmenu.h>
#include <qicon.h>
#include <kstandardaction.h>
#include <qsavefile.h>
#include <qdom.h>

#include "math.h"

#include "skgtraces.h"
#include "skgmainpanel.h"

SKGWebView::SKGWebView(QWidget* iParent, const char* name)
    : QWebView(iParent)
{
    setObjectName(name);
    this->installEventFilter(this);
    page()->installEventFilter(this);
}

SKGWebView::~SKGWebView()
{}

QString SKGWebView::getState()
{
    SKGTRACEINFUNC(10);
    QDomDocument doc(QStringLiteral("SKGML"));
    QDomElement root = doc.createElement(QStringLiteral("parameters"));
    doc.appendChild(root);
    root.setAttribute(QStringLiteral("zoomFactor"), SKGServices::intToString(qMax(qRound(30.0 * log10(zoomFactor())), -10)));
    return doc.toString();
}

void SKGWebView::setState(const QString& iState)
{
    SKGTRACEINFUNC(10);
    QDomDocument doc(QStringLiteral("SKGML"));
    doc.setContent(iState);
    QDomElement root = doc.documentElement();
    QString zoomPosition = root.attribute(QStringLiteral("zoomFactor"));
    if (zoomPosition.isEmpty()) {
        zoomPosition = '0';
    }
    double z = qPow(10, (static_cast<qreal>(SKGServices::stringToInt(zoomPosition)) / 30.0));
    setZoomFactor(z);
    emit zoomChanged(z);
}

void SKGWebView::contextMenuEvent(QContextMenuEvent* iEvent)
{
    if (iEvent) {
        auto menu = new QMenu(this);

        menu->addAction(pageAction(QWebPage::Copy));

        QAction* actPrint = menu->addAction(SKGServices::fromTheme(QStringLiteral("printer")), i18nc("Action", "Print..."));
        connect(actPrint, &QAction::triggered, this, &SKGWebView::onPrint);

        menu->addAction(static_cast<QAction*>(KStandardAction::printPreview(this, SLOT(onPrintPreview()), this)));

        QAction* actExport = menu->addAction(SKGServices::fromTheme(QStringLiteral("document-export")), i18nc("Noun, user action", "Export..."));
        connect(actExport, &QAction::triggered, this, &SKGWebView::onExport);

        menu->popup(this->mapToGlobal(iEvent->pos()));

        iEvent->accept();
    }
}

bool SKGWebView::eventFilter(QObject* iObject, QEvent* iEvent)
{
    SKGTRACEINFUNC(10);
    if (iEvent && iEvent->type() == QEvent::Wheel) {
        QWheelEvent* e = static_cast<QWheelEvent*>(iEvent);
        if (e) {
            if (e->orientation() == Qt::Vertical && QApplication::keyboardModifiers() &Qt::ControlModifier) {
                int numDegrees = e->delta() / 8;
                int numTicks = numDegrees / 15;

                if (numTicks > 0) {
                    onZoomIn();
                } else {
                    onZoomOut();
                }
                e->setAccepted(true);
                return true;
            }
        }
    }
    return QWidget::eventFilter(iObject, iEvent);
}

void SKGWebView::onZoomIn()
{
    _SKGTRACEINFUNC(10);
    int z = qMin(static_cast<int>(qRound(30.0 * log10(zoomFactor()))) + 1, 10);
    setZoomFactor(qPow(10, static_cast<qreal>(z) / 30.0));

    emit zoomChanged(z);
}

void SKGWebView::onZoomOut()
{
    _SKGTRACEINFUNC(10);
    int z = qMax(static_cast<int>(qRound(30.0 * log10(zoomFactor()))) - 1, -10);
    setZoomFactor(qPow(10, static_cast<qreal>(z) / 30.0));

    emit zoomChanged(z);
}

void SKGWebView::onZoomOriginal()
{
    _SKGTRACEINFUNC(10);
    setZoomFactor(0);

    emit zoomChanged(0);
}

void SKGWebView::exportInFile(const QString& iFileName)
{
    QString extension = QFileInfo(iFileName).suffix().toUpper();
    if (extension == QStringLiteral("ODT")) {
        QTextDocument doc;
        doc.setHtml(page()->mainFrame()->toHtml());

        QTextDocumentWriter docWriter(iFileName);
        docWriter.write(&doc);
    } else if (extension == QStringLiteral("PDF")) {
        QPrinter printer;
        printer.setOutputFileName(iFileName);
        print(&printer);
    } else if (extension == QStringLiteral("HTML") || extension == QStringLiteral("HTM")) {
        QSaveFile file(iFileName);
        if (file.open(QIODevice::WriteOnly)) {
            QTextStream out(&file);
            out << page()->mainFrame()->toHtml();

            // Close file
            file.commit();
        }
    } else {
        QImage image(this->size(), QImage::Format_ARGB32);
        QPainter painter(&image);
        this->render(&painter);
        painter.end();
        image.save(iFileName);
    }
}

void SKGWebView::onExport()
{
    _SKGTRACEINFUNC(10);
    QString fileName = SKGMainPanel::getSaveFileName(QStringLiteral("kfiledialog:///IMPEXP"), QStringLiteral("application/pdf text/html application/vnd.oasis.opendocument.text image/png image/jpeg image/gif image/tiff"), this, nullptr);
    if (fileName.isEmpty()) {
        return;
    }

    exportInFile(fileName);

    QDesktopServices::openUrl(QUrl(fileName));
}

void SKGWebView::onPrintPreview()
{
    SKGTRACEINFUNC(10);
    QPointer<QPrintPreviewDialog> dialog = new QPrintPreviewDialog(this);
    connect(dialog.data(), &QPrintPreviewDialog::paintRequested, this, &SKGWebView::print);
    dialog->exec();
    delete dialog;
}

void SKGWebView::onPrint()
{
    _SKGTRACEINFUNC(10);
    QPrinter printer;
    QPointer<QPrintDialog> dialog = new QPrintDialog(&printer, this);
    if (dialog->exec() == QDialog::Accepted) {
        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
        print(&printer);
        QApplication::restoreOverrideCursor();
    }

    delete dialog;
}

