/***************************************************************************
 *   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 plugin to print pages
 *
 * @author Stephane MANKOWSKI
 */
#include "skgprintplugin.h"

#include <KActionCollection>
#include <KStandardAction>
#include <KAboutData>
#include <KGenericFactory>
#include <KTextBrowser>

#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QPainter>
#include <QPicture>
#include <QWebView>
#include <QWebFrame>
#include <qbuffer.h>

#include "skgprint_settings.h"
#include "skgtraces.h"
#include "skgmainpanel.h"
#include "skgtreeview.h"

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGPrintPluginFactory, registerPlugin<SKGPrintPlugin>();)
/**
 * This plugin export.
 */
K_EXPORT_PLUGIN(SKGPrintPluginFactory("skg_print", "skg_print"))

SKGPrintPlugin::SKGPrintPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) :
    SKGInterfacePlugin(iParent),
    m_currentDocument(NULL), m_printAction(NULL), m_printPreviewAction(NULL)
{
    Q_UNUSED(iWidget);
    SKGTRACEINFUNC(10);
}

SKGPrintPlugin::~SKGPrintPlugin()
{
    SKGTRACEINFUNC(10);
    m_currentDocument = NULL;
    m_printAction = NULL;
    m_printPreviewAction = NULL;
}

bool SKGPrintPlugin::setupActions(SKGDocument* iDocument, const QStringList& iArgument)
{
    SKGTRACEINFUNC(10);
    Q_UNUSED(iArgument);

    m_currentDocument = iDocument;

    setComponentData(KGlobal::mainComponent());
    setXMLFile("../skg_print/skg_print.rc");

    m_printAction = KStandardAction::print(this, SLOT(onPrint()), actionCollection());
    registerGlobalAction("print", m_printAction);

    m_printPreviewAction = KStandardAction::printPreview(this, SLOT(onPrintPreview()), actionCollection());
    registerGlobalAction("print_preview", m_printPreviewAction);

    return true;
}

void SKGPrintPlugin::refresh()
{
    SKGTRACEINFUNC(10);
    if (m_currentDocument) {
        bool test = (m_currentDocument->getDatabase() != NULL && SKGMainPanel::getMainPanel()->currentPage() != NULL);
        if (m_printAction) {
            m_printAction->setEnabled(test);
        }
        if (m_printPreviewAction) {
            m_printPreviewAction->setEnabled(test);
        }
    }
}

KConfigSkeleton* SKGPrintPlugin::getPreferenceSkeleton()
{
    return skgprint_settings::self();
}

QString SKGPrintPlugin::title() const
{
    return i18nc("Verb, action to use a printer", "print");
}

int SKGPrintPlugin::getOrder() const
{
    return 2;
}

QStringList SKGPrintPlugin::tips() const
{
    QStringList output;
    output.push_back(i18nc("Description of a tips", "<p>... you can print all opened pages.</p>"));
    return output;
}

void SKGPrintPlugin::onPrint()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    if (SKGMainPanel::getMainPanel()) {
        QPrinter printer(QPrinter::HighResolution);
        QPointer<QPrintDialog> dialog = new QPrintDialog(&printer, SKGMainPanel::getMainPanel());
        dialog->setOption(QAbstractPrintDialog::PrintCurrentPage, true);
        dialog->setMinMax(1, SKGMainPanel::getMainPanel()->getTabWidget()->count());
        if (dialog->exec() == QDialog::Accepted) {
            QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
            print(&printer);
            QApplication::restoreOverrideCursor();
        }
        delete dialog;
    }
}

void SKGPrintPlugin::onPrintPreview()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);
    QPointer<QPrintPreviewDialog> dialog = new QPrintPreviewDialog(SKGMainPanel::getMainPanel());
    connect(dialog, SIGNAL(paintRequested(QPrinter*)), this, SLOT(print(QPrinter*)));
    dialog->exec();
    delete dialog;
}

void SKGPrintPlugin::print(QPrinter* iPrinter)
{
    SKGTRACEINFUNC(10);
    if (SKGMainPanel::getMainPanel() && iPrinter) {
        SKGError err;

        // Get printer options
        int docCopies;
        int pageCopies;
        if (iPrinter->collateCopies()) {
            docCopies = 1;
            pageCopies = iPrinter->actualNumCopies();
        } else {
            docCopies = iPrinter->actualNumCopies();
            pageCopies = 1;
        }
        int fromPage = qMin(iPrinter->fromPage(), iPrinter->toPage());
        int toPage = qMax(iPrinter->fromPage(), iPrinter->toPage());

        // Compute the number of pages
        SKGTabWidget* tabs = SKGMainPanel::getMainPanel()->getTabWidget();
        int nbpages = tabs->count();

        if (fromPage == 0 && toPage == 0) {
            fromPage = 1;
            toPage = nbpages;
        }
        if (iPrinter->printRange() == QPrinter::CurrentPage) {
            fromPage = SKGMainPanel::getMainPanel()->currentPageIndex() + 1;
            toPage = fromPage;
        }

        SKGTRACEL(10) << "Nb copy document=" << docCopies << endl;
        SKGTRACEL(10) << "Nb copy page=" << docCopies << endl;
        SKGTRACEL(10) << "From=" << fromPage << endl;
        SKGTRACEL(10) << "To=" << toPage << endl;

        // Copy document
        QString html;
        for (int c = 1; !err && c <= docCopies; ++c) {
            for (int i = 1; !err && i <= nbpages; ++i) {
                // Compute page
                int pageToTreat = (iPrinter->pageOrder() == QPrinter::LastPageFirst ? nbpages + 1 - i : i);

                // Do we have to print it
                if (pageToTreat >= fromPage && pageToTreat <= toPage) {
                    // Yes, get the widget
                    // Copy pages
                    for (int p = 1; !err && p <= pageCopies; ++p) {
                        SKGTabPage* page = static_cast<SKGTabPage*>(tabs->widget(pageToTreat - 1));
                        if (page) {
                            QList<QWidget*> widgets = page->printableWidgets();
                            int nbw = widgets.count();
                            for (int j = 0; !err && j < nbw; ++j) {
                                QWidget* w = widgets.at(j);
                                if (w) {
                                    SKGTreeView* tw = qobject_cast< SKGTreeView* >(w);
                                    tw = NULL;
                                    if (tw) {
                                        KTextBrowser* tb = tw->getTextBrowser();
                                        if (tb) {
                                            html = html % tb->toHtml();
                                            delete tb;
                                        }
                                    } else {
                                        QWebView* q = qobject_cast< QWebView* >(w);
                                        if (q) {
                                            html = html % q->page()->currentFrame()->toHtml();
                                        } else {
                                            // Save palette
                                            QPalette previousPalette = w->palette();

                                            // Draw in a picture with white background
                                            QImage image(w->size(), QImage::Format_ARGB32);
                                            QPainter painter2(&image);
                                            QPalette palette;
                                            palette.setColor(QPalette::Background, Qt::white);
                                            w->setPalette(palette);
                                            w->render(&painter2);
                                            painter2.end();

                                            // Restore palette
                                            w->setPalette(previousPalette);

                                            QByteArray byteArray;
                                            QBuffer buffer(&byteArray);
                                            image.save(&buffer, "PNG");

                                            QString imgBase64 = QString::fromLatin1(byteArray.toBase64().data());
                                            html = html % "<img src=\"data:image/png;base64," % imgBase64 % "\" />";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // Print
        QWebView toPrint;
        toPrint.setHtml(html);
        qApp->processEvents(QEventLoop::AllEvents, 5000);

        // Reset printer option because already treated
        iPrinter->setPrintRange(QPrinter::AllPages);
        iPrinter->setFromTo(1, nbpages);
        iPrinter->setCollateCopies(false);
        iPrinter->setPageOrder(QPrinter::FirstPageFirst);
        iPrinter->setNumCopies(1);
        iPrinter->setPrintProgram(qApp->applicationName());
        iPrinter->setCreator(qApp->applicationName());
        toPrint.print(iPrinter);

        // status bar
        IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Print successfully done.")))
        else {
            err.addError(ERR_FAIL, i18nc("Error message", "Print failed"));
        }

        // Display error
        SKGMainPanel::displayErrorMessage(err);
    }
}
#include "skgprintplugin.moc"
