# Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
#                    Julien Pivotto <roidelapluie AT gmail.com>
#                    Stefan Bethge <stefan AT lanpartei.de>
#                    Stephan Erb <steve-e AT h3c.de>
# Copyright (C) 2007-2014 Yann Leboulanger <asterix AT lagaule.org>
# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
#
# This file is part of Gajim.
#
# SPDX-License-Identifier: GPL-3.0-only

from typing import NamedTuple

import sys

from gi.repository import Gtk
from gi.repository import Pango

from gajim.common import app
from gajim.common import passwords
from gajim.common.i18n import _

from gajim.gtk.widgets import GajimAppWindow


class Feature(NamedTuple):
    name: str
    available: bool
    tooltip: str
    dependency_u: str
    dependency_w: str
    enabled: bool | None


class Features(GajimAppWindow):
    def __init__(self) -> None:
        GajimAppWindow.__init__(
            self,
            name='Features',
            title=_('Features')
        )

        grid = Gtk.Grid(
            name='FeaturesInfoGrid',
            row_spacing=10,
            width_request=400
        )

        self.feature_listbox = Gtk.ListBox(
            hexpand=True,
            vexpand=True,
            selection_mode=Gtk.SelectionMode.NONE
        )

        grid.attach(self.feature_listbox, 0, 0, 1, 1)

        box = Gtk.Box(spacing=18)
        box.append(grid)
        self.set_child(box)

        for feature in self._get_features():
            self._add_feature(feature)

    def _cleanup(self) -> None:
        pass

    def _add_feature(self, feature: Feature) -> None:
        item = FeatureItem(feature)
        self.feature_listbox.append(item)

    def _get_features(self) -> list[Feature]:
        av_available = app.is_installed('AV') and sys.platform != 'win32'
        notification_sounds_available: bool = (
            app.is_installed('GSOUND') or sys.platform in ('win32', 'darwin'))
        notification_sounds_enabled: bool = app.settings.get('sounds_on')
        spell_check_enabled: bool = app.settings.get('use_speller')

        auto_status = [app.settings.get('autoaway'), app.settings.get('autoxa')]
        auto_status_enabled = bool(any(auto_status))

        return [
            Feature(_('Audio Preview'),
                    app.is_installed('GST'),
                    _('Enables Gajim to provide a Audio preview'),
                    _('Requires: gstreamer-1.0, gst-plugins-base-1.0'),
                    _('No additional requirements'),
                    None),
            Feature(_('Audio / Video Calls'),
                    av_available,
                    _('Enables Gajim to provide Audio and Video chats'),
                    _('Requires: farstream-0.2, gstreamer-1.0, '
                      'gst-plugins-base-1.0, gst-plugins-ugly-1.0, '
                      'gst-libav'),
                    _('Feature not available on Windows'),
                    None),
            Feature(_('Automatic Status'),
                    self._idle_available(),
                    _('Enables Gajim to measure your computer’s idle time in '
                      'order to set your Status automatically'),
                    _('Requires: libxss'),
                    _('No additional requirements'),
                    auto_status_enabled),
            Feature(_('Notification Sounds'),
                    notification_sounds_available,
                    _('Enables Gajim to play sounds for various notifications'),
                    _('Requires: gsound'),
                    _('No additional requirements'),
                    notification_sounds_enabled),
            Feature(_('Secure Password Storage'),
                    passwords.is_keyring_available(),
                    _('Enables Gajim to store Passwords securely instead of '
                      'storing them in plaintext'),
                    _('Requires: gnome-keyring or kwallet'),
                    _('No additional requirements'),
                    app.settings.get('use_keyring')),
            Feature(_('Spell Checker'),
                    app.is_installed('SPELLING'),
                    _('Enables Gajim to spell check your messages while '
                      'composing'),
                    _('Requires: libspelling'),
                    _('No additional requirements'),
                    spell_check_enabled),
            Feature(_('UPnP-IGD Port Forwarding'),
                    app.is_installed('UPNP'),
                    _('Enables Gajim to request your router to forward ports '
                      'for file transfers'),
                    _('Requires: gupnpigd-1.0'),
                    _('Feature not available on Windows'),
                    None)
        ]

    @staticmethod
    def _idle_available() -> bool:
        from gajim.common import idle
        return idle.Monitor.is_available()


class FeatureItem(Gtk.Grid):
    def __init__(self, feature: Feature) -> None:
        Gtk.Grid.__init__(self)
        self.set_column_spacing(12)

        feature_label = Gtk.Label(label=feature.name)
        feature_label.set_halign(Gtk.Align.START)
        self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self._box.append(feature_label)
        self._box.set_tooltip_text(feature.tooltip)

        feature_dependency = Gtk.Label(label=feature.dependency_u)
        feature_dependency.get_style_context().add_class('dim-label')

        if sys.platform == 'win32':
            feature_dependency.set_label(feature.dependency_w)
        else:
            feature_dependency.set_label(feature.dependency_u)

        if not feature.available:
            feature_dependency.set_halign(Gtk.Align.START)
            feature_dependency.set_xalign(0.0)
            feature_dependency.set_yalign(0.0)
            feature_dependency.set_wrap(True)
            feature_dependency.set_wrap_mode(Pango.WrapMode.WORD)
            feature_dependency.set_max_width_chars(50)
            feature_dependency.set_selectable(True)
            self._box.append(feature_dependency)

        self._icon = Gtk.Image()
        self._label_disabled = Gtk.Label(label=_('Disabled in Preferences'))
        self._label_disabled.get_style_context().add_class('dim-label')
        self._set_feature(feature.available, feature.enabled)

        self.attach(self._icon, 0, 0, 1, 1)
        self.attach(self._box, 1, 0, 1, 1)

    def do_unroot(self) -> None:
        Gtk.Grid.do_unroot(self)
        app.check_finalize(self)

    def _set_feature(self, available: bool, enabled: bool | None) -> None:
        self._icon.get_style_context().remove_class('error-color')
        self._icon.get_style_context().remove_class('warning-color')
        self._icon.get_style_context().remove_class('success-color')

        if not available:
            self._icon.set_from_icon_name(
                'window-close-symbolic')
            self._icon.get_style_context().add_class('error-color')
            return

        if enabled is not None and not enabled:
            self._icon.set_from_icon_name(
                'dialog-warning-symbolic')
            self._box.append(self._label_disabled)
            self._icon.get_style_context().add_class('warning-color')
        else:
            self._icon.set_from_icon_name(
                'emblem-ok-symbolic')
            self._icon.get_style_context().add_class('success-color')
