/***************************************************************************
 *   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
 * The grantlee's filter to get items of a document table.
 *
 * @author Stephane MANKOWSKI
 */
#include "skgdocumentfilter.h"
#include "skgtraces.h"
#include "skgdocument.h"
#include "skgmainpanel.h"

#include "grantlee/util.h"

#include <cmath>
#ifdef Q_OS_WIN
#define isnan(a) _isnan(a)
#define isinf(a) !_finite(a)
#else
using std::isnan;
using std::isinf;
#endif

QVariant SKGDocumentTableFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    SKGDocument* doc = qobject_cast< SKGDocument* >(input.value<QObject*>());
    if (doc && argument.isValid()) {
        SKGObjectBase::SKGListSKGObjectBase objects;
        QString table = Grantlee::getSafeString(argument);
        QString wc;
        int pos = table.indexOf(",");
        if (pos != -1) {
            wc = table.right(table.count() - pos - 1);
            table = table.left(pos);
        }

        doc->getObjects(table, wc, objects);
        return qVariantFromValue<>(objects);
    }

    return QVariant();
}

bool SKGDocumentTableFilter::isSafe() const
{
    return true;
}

QVariant SKGDocumentDisplayFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    SKGDocument* doc = qobject_cast< SKGDocument* >(input.value<QObject*>());
    if (doc) return doc->getDisplay(Grantlee::getSafeString(argument));

    return QVariant();
}

bool SKGDocumentDisplayFilter::isSafe() const
{
    return true;
}


QVariant SKGPercentFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    Q_UNUSED(argument);
    SKGMainPanel* mainPanel = SKGMainPanel::getMainPanel();
    SKGDocument* doc = NULL;
    if (mainPanel) doc = mainPanel->getDocument();
    if (doc) {
        QString s = Grantlee::getSafeString(input);
        return QVariant(doc->formatPercentage(SKGServices::stringToDouble(s)));
    }
    return QVariant();
}

bool SKGPercentFilter::isSafe() const
{
    return true;
}

QVariant SKGDumpFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    Q_UNUSED(argument);

    if (input.isValid()) {
        QObject* obj = input.value<QObject*>();
        if (obj) {
            const QMetaObject* metaObject = obj->metaObject();
            QString table = "<table>";
            int nb = metaObject->propertyCount();
            for (int i = 0; i < nb; ++i) {
                QVariant val = SKGDumpFilter::doFilter(obj->property(metaObject->property(i).name()), QVariant(), autoescape);
                table += QString("<tr><td>") % metaObject->property(i).name() % "</td><td>" % val.toString() % "</td></tr>";
            }
            table += "</table>";
            return QVariant(table);
        } else if (input.canConvert<SKGObjectBase>()) {
            SKGObjectBase obj = input.value<SKGObjectBase>();
            SKGQStringQStringMap att = obj.getAttributes();
            QStringList keys = att.keys();
            QString table = "<table>";
            int nb = keys.count();
            for (int i = 0; i < nb; ++i) {
                table += QString("<tr><td>") % keys.at(i) % "</td><td>" % att[keys.at(i)] % "</td></tr>";
            }
            table += "</table>";
            return QVariant(table);
        } else if (input.canConvert(QVariant::List)) {
            QList<QVariant> l = input.toList();
            int nb = l.count();
            QString table = "<table>";
            for (int i = 0; i < nb; ++i) {
                QVariant val = SKGDumpFilter::doFilter(l.at(i), QVariant(), autoescape);
                table += QString("<tr><td>") % SKGServices::intToString(i) % "</td><td>" % val.toString() % "</td></tr>";
            }
            table += "</table>";
            return QVariant(table);
        } else if (input.canConvert<SKGObjectBase::SKGListSKGObjectBase>()) {
            SKGObjectBase::SKGListSKGObjectBase l = input.value<SKGObjectBase::SKGListSKGObjectBase>();
            int nb = l.count();
            QString table;
            if (nb) {
                table = "<table><tr><th>#</th>";
                for (int i = 0; i < nb; ++i) {
                    SKGObjectBase obj = l.at(i);
                    SKGQStringQStringMap att = obj.getAttributes();
                    QStringList keys = att.keys();
                    QString line = QString("<tr><td>") % SKGServices::intToString(i) % "</td>";
                    int nbc = keys.count();
                    for (int j = 0; j < nbc; ++j) {
                        if (i == 0) table += QString("<th>") % keys.at(j) % "</th>";
                        line += QString("<td>") % att[keys.at(j)] % "</td>";
                    }
                    if (i == 0) table += "</tr>";
                    line += "</tr>";

                    table += line;
                }
                table += "</table>";
            }
            return QVariant(table);
        } else {
            return QVariant(input.toString());
        }
    }

    return QVariant();
}

bool SKGDumpFilter::isSafe() const
{
    return true;
}

QVariant SKGMoneyFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    QString arg = Grantlee::getSafeString(argument);
    SKGMainPanel* mainPanel = SKGMainPanel::getMainPanel();
    SKGDocument* doc = NULL;
    if (mainPanel) doc = mainPanel->getDocument();
    if (doc) return QVariant(doc->formatMoney(SKGServices::stringToDouble(Grantlee::getSafeString(input)), doc->getUnit(arg == "2" ? "secondary" : "primary")));
    return QVariant();
}

bool SKGMoneyFilter::isSafe() const
{
    return true;
}

QVariant SKGUrlEncodeFilter::doFilter(const QVariant& input, const QVariant& argument, bool autoescape) const
{
    Q_UNUSED(autoescape);
    Q_UNUSED(argument);
    return QVariant(SKGServices::encodeForUrl(Grantlee::getSafeString(input)));
}

bool SKGUrlEncodeFilter::isSafe() const
{
    return true;
}
