"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 25.11.20

"""

from django.core.paginator import PageNotAnInteger, EmptyPage
from django.db.models import F
from django.http import HttpRequest
from django.template.loader import render_to_string
from django.utils.html import format_html
import django_tables2 as tables
from django.utils.translation import gettext_lazy as _

from konova.models import BaseObject, GeoReferencedMixin, ShareableObjectMixin
from konova.settings import PAGE_SIZE_DEFAULT, PAGE_PARAM, RESULTS_PER_PAGE_PARAM, PAGE_SIZE_OPTIONS


class BaseTable(tables.tables.Table):
    results_per_page_choices = PAGE_SIZE_OPTIONS
    results_per_page_chosen = None
    results_per_page_parameter = RESULTS_PER_PAGE_PARAM
    add_new_entries = True
    add_new_url = None
    title = None
    subtitle = ""

    class Meta:
        attrs = {
            "class": "table table-hover table-responsive-md table-responsive-sm",
        }

    def __init__(self, request: HttpRequest = None, queryset=None, *args, **kwargs):
        self.user = request.user or None
        kwargs["data"] = queryset
        kwargs["request"] = request
        super().__init__(*args, **kwargs)
        self.results_per_page_chosen = int(request.GET.get(RESULTS_PER_PAGE_PARAM, PAGE_SIZE_DEFAULT))
        try:
            self.paginate(
                page=request.GET.get(PAGE_PARAM, 1),
                per_page=self.results_per_page_chosen,
            )
        except (PageNotAnInteger, EmptyPage) as e:
            self.paginate(
                page=1,
                per_page=self.results_per_page_chosen,
            )

    def render_link(self, tooltip: str, href: str, txt: str, new_tab: bool = False):
        """
        Returns an <a> html element using given parameters
        """
        new_tab = "_blank" if new_tab else "_self"
        return format_html(
            "<a href={} target='{}' title='{}'>{}</a>",
            href,
            new_tab,
            tooltip,
            txt,
        )

    def render_delete_btn(self, tooltip: str = None, href: str = None):
        """
        Returns a remover icon with <a> support as html element using given parameters
        """
        return format_html(
            "<a href={} title='{}'><button class='button small'><em class='fas fa-trash-alt'></em></button></a>",
            href,
            tooltip,
        )

    def render_edit_btn(self, tooltip: str = None, href: str = None):
        """
        Returns a remover icon with <a> support as html element using given parameters
        """
        return format_html(
            "<a href={} title='{}'><button class='button small'><em class='fas fa-edit'></em></button></a>",
            href,
            tooltip,
        )

    def render_open_btn(self, tooltip: str = None, href: str = None, new_tab: bool = False):
        """
        Returns a remover icon with <a> support as html element using given parameters
        """
        return format_html(
            "<a href={} title='{}' target='{}'><button class='button small'><em class='fas fa-sign-in-alt'></em></button></a>",
            href,
            tooltip,
            "_blank" if new_tab else ""
        )

    def render_boolean(self, tooltip: str = None, val: bool = False):
        """
        Returns a remover icon with <a> support as html element using given parameters
        """
        icon = "fas fa-check-circle true" if val else "fas fa-times-circle false"
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icon
        )

    def render_checked_star(self, tooltip: str = None, icn_filled: bool = False):
        """
        Returns a star icon
        """
        icon = "fas fa-star check-star" if icn_filled else "far fa-star"
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icon
        )

    def render_previously_checked_star(self, tooltip: str = None):
        """
        Returns a star icon for a check action in the past
        """
        icon = "fas fa-star rlp-gd-inv"
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icon
        )

    def render_bookmark(self, tooltip: str = None, icn_filled: bool = False):
        """
        Returns a bookmark icon
        """
        icon = "fas fa-bookmark registered-bookmark" if icn_filled else "far fa-bookmark"
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icon
        )

    def render_stop(self, tooltip: str = None, icn_filled: bool = False):
        """
        Returns a stop icon
        """
        icon = "fas fa-ban rlp-r-inv" if icn_filled else "fas fa-ban rlp-gd-inv"
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icon
        )

    def render_icn(self, tooltip: str = None, icn_class: str = None):
        """
        Returns a rendered fontawesome icon
        """
        return format_html(
            "<em title='{}' class='{}'></em>",
            tooltip,
            icn_class,
        )


class TableRenderMixin:
    """ Holds different render methods for general purposes

    """
    def render_t(self, value, record: BaseObject):
        """ Renders a BaseObject title

        Args:
            value ():
            record ():

        Returns:

        """
        value_orig = value
        max_length = 75
        if len(value) > max_length:
            value = f"{value[:max_length]}..."
        value = format_html(
            '<div title="{}">{}</div>',
            value_orig,
            value
        )
        return value

    def render_d(self, value, record: GeoReferencedMixin):
        """ Renders the parcel district column

        Args:
            value (str): The intervention geometry
            record (GeoReferencedMixin): The record

        Returns:

        """
        parcels = value.get_underlying_parcels().values_list(
            "parcel_group__name",
            flat=True
        ).distinct()
        html = render_to_string(
            "table/gmrkng_col.html",
            {
                "entries": parcels,
                "geometry": record.geometry
            }
        )
        return html

    def render_e(self, value, record: ShareableObjectMixin):
        """ Renders the editable column

        Args:
            value (str): The identifier value
            record (ShareableObjectMixin): The record

        Returns:

        """
        html = ""
        is_entry_shared = record.is_shared_with(self.user)

        html += self.render_icn(
            tooltip=_("Full access granted") if is_entry_shared else _("Access not granted"),
            icn_class="fas fa-edit rlp-r-inv" if is_entry_shared else "far fa-edit",
        )
        return format_html(html, None)


class TableOrderMixin:
    """
    Holds different order_by methods for general purposes

    """
    def order_lm(self, queryset, is_asc):
        queryset = queryset.order_by(F('modified__timestamp').desc(nulls_last=True))
        return (queryset, is_asc)
