"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 19.08.22

"""
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views import View

from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
from intervention.models import Intervention
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import default_group_required, shared_access_required
from konova.forms import SimpleGeomForm
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, \
    CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, \
    GEOMETRIES_IGNORED_TEMPLATE
from konova.views.identifier import AbstractIdentifierGeneratorView
from konova.views.index import AbstractIndexView


class IndexInterventionView(AbstractIndexView):
    def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
        """
        Renders the index view for Interventions

        Args:
            request (HttpRequest): The incoming request

        Returns:
            A rendered view
        """
        # Filtering by user access is performed in table filter inside InterventionTableFilter class
        interventions = Intervention.objects.filter(
            deleted=None,  # not deleted
        ).select_related(
            "legal"
        ).order_by(
            "-modified__timestamp"
        )
        table = InterventionTable(
            request=request,
            queryset=interventions
        )
        context = {
            "table": table,
            TAB_TITLE_IDENTIFIER: _("Interventions - Overview"),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)


class NewInterventionView(LoginRequiredMixin, View):
    _TEMPLATE = "intervention/form/view.html"

    @method_decorator(default_group_required)
    def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:

        """
        Renders a view for a new intervention creation

        Args:
            request (HttpRequest): The incoming request

        Returns:

        """
        data_form = NewInterventionForm()
        geom_form = SimpleGeomForm(read_only=False)
        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("New intervention"),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)

    @method_decorator(default_group_required)
    def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:

        """
        Renders a view for a new intervention creation

        Args:
            request (HttpRequest): The incoming request

        Returns:

        """
        data_form = NewInterventionForm(request.POST or None)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False)

        if data_form.is_valid() and geom_form.is_valid():
            generated_identifier = data_form.cleaned_data.get("identifier", None)
            intervention = data_form.save(request.user, geom_form)
            if generated_identifier != intervention.identifier:
                messages.info(
                    request,
                    IDENTIFIER_REPLACED.format(
                        generated_identifier,
                        intervention.identifier
                    )
                )

            messages.success(request, _("Intervention {} added").format(intervention.identifier))
            if geom_form.has_geometry_simplified():
                messages.info(
                    request,
                    GEOMETRY_SIMPLIFIED
                )

            num_ignored_geometries = geom_form.get_num_geometries_ignored()
            if num_ignored_geometries > 0:
                messages.info(
                    request,
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
                )
            return redirect("intervention:detail", id=intervention.id)

        else:
            messages.error(request, FORM_INVALID, extra_tags="danger", )
        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("New intervention"),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)


class InterventionIdentifierGeneratorView(AbstractIdentifierGeneratorView):
    _MODEL = Intervention


class EditInterventionView(LoginRequiredMixin, View):
    _TEMPLATE = "intervention/form/view.html"

    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Intervention, "id"))
    def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
        """
        Renders a view for editing interventions

        Args:
            request (HttpRequest): The incoming request
            id (str): The intervention identifier

        Returns:
            HttpResponse: The rendered view
        """

        # Get object from db
        intervention = get_object_or_404(Intervention, id=id)
        if intervention.is_recorded:
            messages.info(
                request,
                RECORDED_BLOCKS_EDIT
            )
            return redirect("intervention:detail", id=id)

        # Create forms, initialize with values from db/from POST request
        data_form = EditInterventionForm(request.POST or None, instance=intervention)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=intervention)
        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)


    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Intervention, "id"))
    def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:
        """
        Process saved form content

        Args:
            request (HttpRequest): The incoming request
            id (str): The intervention id

        Returns:
            HttpResponse:
        """
        # Get object from db
        intervention = get_object_or_404(Intervention, id=id)
        if intervention.is_recorded:
            messages.info(
                request,
                RECORDED_BLOCKS_EDIT
            )
            return redirect("intervention:detail", id=id)

        # Create forms, initialize with values from db/from POST request
        data_form = EditInterventionForm(request.POST or None, instance=intervention)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=intervention)
        if data_form.is_valid() and geom_form.is_valid():
            # The data form takes the geom form for processing, as well as the performing user
            # Save the current state of recorded|checked to inform the user in case of a status reset due to editing
            intervention_is_checked = intervention.checked is not None
            intervention = data_form.save(request.user, geom_form)
            messages.success(request, _("Intervention {} edited").format(intervention.identifier))
            if intervention_is_checked:
                messages.info(request, CHECK_STATE_RESET)
            if geom_form.has_geometry_simplified():
                messages.info(
                    request,
                    GEOMETRY_SIMPLIFIED
                )
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
            if num_ignored_geometries > 0:
                messages.info(
                    request,
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
                )
            return redirect("intervention:detail", id=intervention.id)
        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("Edit {}").format(intervention.identifier),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)
