"""
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.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 compensation.forms.compensation import EditCompensationForm, NewCompensationForm
from compensation.models import Compensation
from compensation.tables.compensation import CompensationTable
from intervention.models import Intervention
from konova.contexts import BaseContext
from konova.decorators import shared_access_required, default_group_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, PARAMS_INVALID, \
    IDENTIFIER_REPLACED, COMPENSATION_ADDED_TEMPLATE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
from konova.views.identifier import AbstractIdentifierGeneratorView
from konova.views.index import AbstractIndexView


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

        Args:
            request (HttpRequest): The incoming request

        Returns:
            A rendered view
        """
        compensations = Compensation.objects.filter(
            deleted=None,  # only show those which are not deleted individually
            intervention__deleted=None,  # and don't show the ones whose intervention has been deleted
        ).order_by(
            "-modified__timestamp"
        )
        table = CompensationTable(
            request=request,
            queryset=compensations
        )
        context = {
            "table": table,
            TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
        }
        context = BaseContext(request, context).context
        return render(request, self._TEMPLATE, context)


class NewCompensationView(LoginRequiredMixin, View):
    _TEMPLATE = "compensation/form/view.html"

    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Intervention, "intervention_id"))
    def get(self, request: HttpRequest, intervention_id: str = None, *args, **kwargs) -> HttpResponse:
        """
        Renders a view for new compensation

        A compensation creation may be called directly from the parent-intervention object. If so - we may take
        the intervention's id and directly link the compensation to it.

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

        Returns:

        """
        if intervention_id:
            # If the parent-intervention is recorded, we are not allowed to change anything on it's data.
            # Not even adding new child elements like compensations!
            intervention = get_object_or_404(Intervention, id=intervention_id)
            recording_state_blocks_actions = intervention.is_recorded
            if recording_state_blocks_actions:
                messages.info(
                    request,
                    RECORDED_BLOCKS_EDIT
                )
                return redirect("intervention:detail", id=intervention_id)

        data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False)

        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("New compensation"),
        }
        context = BaseContext(request, context).context

        return render(request, self._TEMPLATE, context)

    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Intervention, "intervention_id"))
    def post(self, request: HttpRequest, intervention_id: str = None, *args, **kwargs) -> HttpResponse:

        """
        Renders a view for a new compensation creation

        Args:
            request (HttpRequest): The incoming request

        Returns:

        """
        if intervention_id:
            # If the parent-intervention is recorded, we are not allowed to change anything on it's data.
            # Not even adding new child elements like compensations!
            intervention = get_object_or_404(Intervention, id=intervention_id)
            recording_state_blocks_actions = intervention.is_recorded
            if recording_state_blocks_actions:
                messages.info(
                    request,
                    RECORDED_BLOCKS_EDIT
                )
                return redirect("intervention:detail", id=intervention_id)

        data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
        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)
            comp = data_form.save(request.user, geom_form)
            if generated_identifier != comp.identifier:
                messages.info(
                    request,
                    IDENTIFIER_REPLACED.format(
                        generated_identifier,
                        comp.identifier
                    )
                )
            messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.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("compensation:detail", id=comp.id)
        else:
            messages.error(request, FORM_INVALID, extra_tags="danger", )

        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("New compensation"),
        }
        context = BaseContext(request, context).context

        return render(request, self._TEMPLATE, context)


class CompensationIdentifierGeneratorView(AbstractIdentifierGeneratorView):
    _MODEL = Compensation


class EditCompensationView(LoginRequiredMixin, View):
    _TEMPLATE = "compensation/form/view.html"

    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Compensation, "id"))
    def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:

        """
        Renders a view for editing compensations

        Args:
            request (HttpRequest): The incoming request

        Returns:

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

        # Create forms, initialize with values from db/from POST request
        data_form = EditCompensationForm(request.POST or None, instance=comp)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)

        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
        }
        context = BaseContext(request, context).context

        return render(request, self._TEMPLATE, context)

    @method_decorator(default_group_required)
    @method_decorator(shared_access_required(Compensation, "id"))
    def post(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse:

        """
        Renders a view for editing compensations

        Args:
            request (HttpRequest): The incoming request

        Returns:

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

        # Create forms, initialize with values from db/from POST request
        data_form = EditCompensationForm(request.POST or None, instance=comp)
        geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
        if data_form.is_valid() and geom_form.is_valid():
            # Preserve state of intervention checked to determine whether the user must be informed or not
            # about a change of the check state
            intervention_is_checked = comp.intervention.checked is not None
            # The data form takes the geom form for processing, as well as the performing user
            comp = data_form.save(request.user, geom_form)
            if intervention_is_checked:
                messages.info(request, CHECK_STATE_RESET)
            messages.success(request, _("Compensation {} edited").format(comp.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("compensation:detail", id=comp.id)
        else:
            messages.error(request, FORM_INVALID, extra_tags="danger", )

        context = {
            "form": data_form,
            "geom_form": geom_form,
            TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
        }
        context = BaseContext(request, context).context

        return render(request, self._TEMPLATE, context)