import logging

from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.utils.translation import gettext_lazy

from django.db import models

from core.fields import IntegerField
from devices.models.endpoint_device import EndpointModel
from inputs.enums import LogInputType, AdjustDatetime
from devices.models.sensor import ArmaSensor

_log = logging.getLogger(__name__)


class LogInput(models.Model):
    label = models.CharField(max_length=128,
                             verbose_name=gettext_lazy("Name"),
                             help_text=gettext_lazy('Name of the input'), unique=True)
    type = models.CharField(max_length=128,
                            choices=LogInputType.choices,
                            verbose_name=gettext_lazy("Type"),
                            help_text=gettext_lazy("Type of loginput"))
    can_delete = models.BooleanField(verbose_name=gettext_lazy('Can delete'),
                                     help_text=gettext_lazy('Can user delete this input'),
                                     default=False)
    config_file_name = models.CharField(max_length=1024,
                                        null=True,
                                        blank=True,
                                        verbose_name=gettext_lazy('Config file name'),
                                        help_text=gettext_lazy('File name of generated config'))
    adjust_datetime = IntegerField(choices=AdjustDatetime.choices, default=AdjustDatetime.LOCAL,
                                   verbose_name=gettext_lazy("Adjust datetime"))


class SensorGetterMixin:
    def get_sensor(self):
        raise NotImplementedError()


class LogInputArmaIF(SensorGetterMixin, models.Model):
    input = models.OneToOneField(LogInput,
                                 on_delete=models.CASCADE,
                                 primary_key=True)
    port = IntegerField(min_value=1500,
                        max_value=65535,
                        verbose_name=gettext_lazy('Port'),
                        help_text=gettext_lazy("Input port number (UDP)"),
                        unique=True,
                        error_messages={
                            'unique': gettext_lazy('This port is already in use')
                        })
    sensor = models.OneToOneField(ArmaSensor, on_delete=models.SET_NULL,
                                  null=True, blank=True)

    def get_sensor(self):
        return self.sensor


class LogInputEndpoint(SensorGetterMixin, models.Model):
    input = models.OneToOneField(LogInput, on_delete=models.CASCADE, primary_key=True)
    port = IntegerField(min_value=1500,
                               max_value=65535,
                               verbose_name=gettext_lazy('Port'),
                               help_text=gettext_lazy("Input port number (UDP)"),
                               unique=True,
                               error_messages={
                                   'unique': gettext_lazy('This port is already in use')
                               })
    endpoint = models.OneToOneField(EndpointModel, on_delete=models.SET_NULL, null=True, blank=True)

    def get_sensor(self):
        return self.endpoint


@receiver(pre_delete, sender=EndpointModel)
def pre_delete_endpoint_log_input(sender, **kwargs):
    endpoint = kwargs['instance']

    _log.info(f"Removing log input for [{endpoint.name}]")
    endpointInputList = list(LogInputEndpoint.objects.filter(endpoint=endpoint))
    for item in endpointInputList:
        item.input.delete()
        item.delete()


@receiver(pre_delete, sender=ArmaSensor)
def pre_delete_arma_log_input(sender, **kwargs):
    sensor = kwargs['instance']

    _log.info(f"Removing log input for [{sensor.name}]")
    armaInputList = list(LogInputArmaIF.objects.filter(sensor=sensor))
    for item in armaInputList:
        item.input.delete()
        item.delete()
