import sys
import logging
from PyQt5 import QtCore, QtDBus
from vorta.models import SettingsModel

logger = logging.getLogger(__name__)


class VortaNotifications:
    """
    Usage:

    notifier = Notifications.pick()()
    notifier.deliver('blah', 'blah blah')
    """
    @classmethod
    def pick(cls):
        if sys.platform == 'darwin':
            return DarwinNotifications()
        elif QtDBus.QDBusConnection.sessionBus().isConnected():
            return DBusNotifications()
        else:
            logger.warning('could not pick valid notification class')
            return cls()

    def deliver(self, title, text, level='info'):
        """Dummy notifier if we're not on macOS or Linux notifier isn't available."""
        pass

    def notifications_suppressed(self, level):
        """Decide if notification is sent or not based on settings and level."""
        if not SettingsModel.get(key='enable_notifications').value:
            logger.debug('notifications suppressed')
            return True
        if level == 'info' and not SettingsModel.get(key='enable_notifications_success').value:
            logger.debug('success notifications suppressed')
            return True

        logger.debug('notification not suppressed')
        return False


class DarwinNotifications(VortaNotifications):
    """
    Notify via notification center and pyobjc bridge.
    """

    def deliver(self, title, text, level='info'):
        if self.notifications_suppressed(level):
            return

        from Foundation import NSUserNotification, NSUserNotificationCenter
        notification = NSUserNotification.alloc().init()
        notification.setTitle_(title)
        notification.setInformativeText_(text)
        center = NSUserNotificationCenter.defaultUserNotificationCenter()
        if center is not None:  # Only works when run from app bundle.
            return center.deliverNotification_(notification)


class DBusNotifications(VortaNotifications):
    """
    Use qt-dbus to send notifications.

    Adapted from http://codito.in/notifications-in-qt-over-dbus/
    """

    URGENCY = {'info': 1, 'error': 2}

    def __init__(self):
        pass

    def _dbus_notify(self, header, msg, level='info'):
        item = "org.freedesktop.Notifications"
        path = "/org/freedesktop/Notifications"
        interface = "org.freedesktop.Notifications"
        app_name = "vorta"
        v = QtCore.QVariant(12321)  # random int to identify all notifications
        if v.convert(QtCore.QVariant.UInt):
            id_replace = v
        icon = ""
        title = header
        text = msg
        actions_list = QtDBus.QDBusArgument([], QtCore.QMetaType.QStringList)
        hint = {'urgency': self.URGENCY[level]}
        time = 5000   # milliseconds for display timeout

        bus = QtDBus.QDBusConnection.sessionBus()
        notify = QtDBus.QDBusInterface(item, path, interface, bus)
        if notify.isValid():
            x = notify.call(QtDBus.QDBus.AutoDetect, "Notify", app_name,
                            id_replace, icon, title, text,
                            actions_list, hint, time)
            if x.errorName():
                logger.warning("Failed to send notification!")
                logger.warning(x.errorMessage())
        else:
            logger.warning("Invalid dbus interface")

    def deliver(self, title, text, level='info'):
        if self.notifications_suppressed(level):
            return

        self._dbus_notify(title, text)