from django.forms.widgets import Widget
from django.utils.translation import gettext_lazy

from dashboard.models import DashboardLayout
from perms.models import Perm

from django.conf import settings
from license_info.tools import check_features
import logging

_log = logging.getLogger()

LICENSE_FEATURE_EVENT_PROCESSING = getattr(settings, 'LICENSE_FEATURE_EVENT_PROCESSING')

# Map license features to restricted widgets
FEATURES_MAP = {
    LICENSE_FEATURE_EVENT_PROCESSING: ["correlator-info"]
}


def check_widget_license(widget):
    """Check if widget allowed in current license
    @return True if widget is allowed and False if not"""
    for feature, bad_widgets in FEATURES_MAP.items():
        if widget.type in bad_widgets:
            return check_features([feature])

    return True


def all_subclasses(cls):
    """
    Get all subclasses of class

    :see: https://stackoverflow.com/a/3862957

    :param cls: Class, to find subclasses
    :return: List of cls subclasses
    """
    return set(cls.__subclasses__()).union(
        [s for c in cls.__subclasses__() for s in all_subclasses(c)])


def get_widget_list_from_user(user):
    """
    Get list of available for user widgets
    :param user: User, who want to see widgets
    :return: List of available widgets

    """
    widgets_list = all_subclasses(DashboardWidget)

    # Get user widgets, that are on layout
    user_widgets = DashboardLayout.objects.get(user=user)
    widgets_ids = []
    for layout_widget in user_widgets.widgets:
        widgets_ids.append(layout_widget['id'])

    # Creating a filtered list of widgets, without widgets on user layout
    filtered_widgets_list = []

    # Remove widget if lt is restricted by license
    widgets_list = [cur for cur in widgets_list if check_widget_license(cur)]

    for w in widgets_list:
        if w.type not in widgets_ids:
            filtered_widgets_list.append(w)

    if user is None:
        return widgets_list

    return [cur for cur in filtered_widgets_list if cur.user_can_see_widget(self=cur, user=user) is True]


class DashboardWidget(Widget):
    """
    Base dashboard widget
    """
    type = 'base'
    label = gettext_lazy('Widget')
    perms = []
    template_name = ''

    def user_can_see_widget(self, user):
        """
        Check if user can see this widget

        Superuser can see all widgets
        :param user: User to check
        :return: True if user can see widget and false if not
        """
        if user.is_superuser:
            return True

        for cur in self.perms:
            if not user.has_perm(Perm.perm_req(cur)):
                return False

        return True


class IncsByImportance(DashboardWidget):
    type = 'incs-by-importance'
    label = gettext_lazy('Incidents by importance')
    perms = [Perm.can_view_incidents]


class IncsByCategory(DashboardWidget):
    type = 'incs-by-category'
    label = gettext_lazy('Incidents by category')
    perms = [Perm.can_view_incidents]


class SysInfoWidget(DashboardWidget):
    type = 'sys-info'
    label = gettext_lazy('System information')
    perms = [Perm.can_view_sys_info]


class ServicesWidget(DashboardWidget):
    type = 'services'
    label = gettext_lazy('Services')
    perms = [Perm.can_view_sys_info]


# TODO: Add top IDS events widget when correlator is ready
# class OpenedIncidentsWidget(DashboardWidget):
#     type = 'opened-incs'
#     label = gettext_lazy('Opened Incidents')
#     perms = [Perm.can_view_incidents]


class IncsByTimeWidget(DashboardWidget):
    type = 'incs-by-time'
    label = gettext_lazy('Incidents by time')
    perms = [Perm.can_view_incidents]


# TODO: Add events by time widget when correlator is ready
# class EventsByTimeWidget(DashboardWidget):
#     type = 'events-by-time'
#     label = gettext_lazy('Events by time')
#     perms = [Perm.can_view_events]


class AssetsByIncsWidget(DashboardWidget):
    type = 'assets_by_incs'
    label = gettext_lazy('Assets by incidents')
    perms = [Perm.can_view_incidents, Perm.can_view_assets_list]


# TODO: Add top IDS events widget when correlator is ready
# class TopIdsEvents(DashboardWidget):
#     type = 'top-ids-events'
#     label = gettext_lazy('Top IDS events')
#     perms = [Perm.can_view_ids_events]


class CorrelatorInfoWidget(DashboardWidget):
    type = 'correlator-info'
    label = gettext_lazy('Correlator')
    perms = [Perm.can_view_correlation_rules_list]


def get_widget_type_with_perms_map() -> dict:
    all_widget = all_subclasses(DashboardWidget)
    return {widget.type: widget.perms for widget in all_widget}
