/*
 *   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 "notifications.h"


FDNotifications::FDNotifications(QObject *parent) : QObject(parent)
{
    qDebug() << "Creating FreeDesktop Notifier";
    m_notificationsAvailable = false; // Init as false, detect later
    m_notificationType = FDNotifications::SystemNotifications;
    m_notificationDuration = 4000;    // Milliseconds


#ifdef QT_DBUS_LIB
    m_busConnection = new QDBusConnection(QDBusConnection::sessionBus());
    if (m_busConnection->isConnected())
    {
        QDBusReply<QStringList> busReply = m_busConnection->interface()
                                                          ->registeredServiceNames();
        qDebug() << "Listing D-Bus services...";
        if (busReply.isValid())
        {
            foreach (const QString serviceName, busReply.value())
            {
                if (serviceName == "org.freedesktop.Notifications")
                {
                    qDebug() << "org.freedesktop.Notifications D-Bus service found!";
                    m_notificationsAvailable = true;
                }
            }
        }
    }
    else
    {
        qDebug() << "D-Bus unavailable!";
        m_notificationsAvailable = false;
    }
#endif

    qDebug() << "FreeDesktop Notifier created";
}


FDNotifications::~FDNotifications()
{
#ifdef QT_DBUS_LIB
    delete m_busConnection;
#endif
    qDebug() << "FreeDesktop Notifier destroyed";
}




bool FDNotifications::areNotificationsAvailable()
{
    qDebug() << "Are notifications available?" << m_notificationsAvailable;
    return m_notificationsAvailable;
}

void FDNotifications::setNotificationOptions(int style, int duration,
                                             bool notifyNewTL, bool notifyHLTL,
                                             bool notifyNewMW, bool notifyHLMW,
                                             bool notifyErr)
{
    m_notificationType = style;
    m_notificationDuration = duration * 1000; // To milliseconds

    m_notifyNewTimeline  = notifyNewTL;
    m_notifyHLTimeline   = notifyHLTL;
    m_notifyNewMeanwhile = notifyNewMW;
    m_notifyHLMeanwhile  = notifyHLMW;
    m_notifyErrors       = notifyErr;

    qDebug() << "Notification type set to"
             << m_notificationType << "-- FD.o/Qt/none; Duration:"
             << m_notificationDuration;
    qDebug() << "Things to notify:"
             << m_notifyNewTimeline << m_notifyHLTimeline
             << m_notifyNewMeanwhile << m_notifyHLMeanwhile
             << m_notifyErrors;
}

void FDNotifications::setCurrentUserId(QString newId)
{
    m_currentUserId = newId;
}


bool FDNotifications::getNotifyNewTimeline()
{
    return m_notifyNewTimeline;
}

bool FDNotifications::getNotifyHLTimeline()
{
    return m_notifyHLTimeline;
}

bool FDNotifications::getNotifyNewMeanwhile()
{
    return m_notifyNewMeanwhile;
}

bool FDNotifications::getNotifyHLMeanwhile()
{
    return m_notifyHLMeanwhile;
}

bool FDNotifications::getNotifyErrors()
{
    return m_notifyErrors;
}



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



void FDNotifications::showMessage(QString message)
{
    // if notifications are disabled
    if (m_notificationType == FDNotifications::NoNotifications)
    {
        return;
    }

    const QString notificationTitle = "Dianara - " + m_currentUserId;

    // If FD.org notifications are not available, or Qt's Balloon ones are selected
    if (!m_notificationsAvailable
       || m_notificationType == FDNotifications::FallbackNotifications)
    {
        qDebug() << "FreeDesktop Notifications are NOT available, "
                    "or balloon notifications selected";

        // Clean up possible HTML, since Qt's balloons don't support it
        message.remove("<b>");
        message.remove("</b>");
        message.remove("<i>");
        message.remove("</i>");
        message.remove("<u>");
        message.remove("</u>");
        message.replace("<br>", "\n");

        emit showFallbackNotification(notificationTitle,
                                      message,
                                      m_notificationDuration);

        return;
    }


    // Only when building with D-Bus support
#ifdef QT_DBUS_LIB
    message.replace("\n", "<br>"); // use HTML newlines
    // HTML newlines break notifications in Xfce; \n works, but is not actually
    // shown as newline in Plasma 4's notifications.
    // However, \n works fine in Plasma 5's notifications.

    QDBusMessage dBusMessage = QDBusMessage::createMethodCall(
                                 "org.freedesktop.Notifications",
                                 "/org/freedesktop/Notifications",
                                 QString(),
                                 QStringLiteral("Notify"));


    // --- D-Bus Notify call ----------------------------------------------
    // method uint org.freedesktop.Notifications.Notify(QString app_name,
    // uint replaces_id, QString app_icon, QString summary, QString body,
    // QStringList actions, QVariantMap hints, int timeout)

    QList<QVariant> arguments;
    arguments << QStringLiteral("Dianara");     // app_name
    arguments << uint(0);                       // replaces_id
    if (QIcon::hasThemeIcon("dianara"))
    {
        arguments << QStringLiteral("dianara"); // app_icon, if "dianara" icon is in theme
    }
    else
    {                                           // app_icon otherwise
        arguments << QStringLiteral("dialog-information");
    }

    // Notification button handled on MainWindow::onNotificationAction()
    const QStringList actions = QStringList{
                                 QString("dianara_%1_show").arg(qApp->applicationPid()),
                                 tr("Show") }; // Could use "default" as ID, and no visible name
    arguments << notificationTitle;
    arguments << message;
    arguments << actions;
    arguments << QVariantMap();                 // hints
    arguments << m_notificationDuration;        // timeout, in milliseconds

    dBusMessage.setArguments(arguments);


    qDebug() << "Sending DBUS call to org.freedesktop.Notifications Notify()";
    m_busConnection->asyncCall(dBusMessage);
#endif
}
