"""Track basic IRC settings and similar."""
import logging
import re

from django.conf import settings
from django.db import models
from django.utils import timezone

log = logging.getLogger('ircbot.models')


class LowerCaseCharField(models.CharField):
    """Provide a case-insensitive, forced-lower CharField."""

    def get_prep_value(self, value):
        """Manipulate the field value to make it lowercase."""
        value = super(LowerCaseCharField, self).get_prep_value(value)
        if value is not None:
            value = value.lower()
        return value


class Alias(models.Model):
    """Allow for aliasing of arbitrary regexes to normal supported commands."""

    pattern = models.CharField(max_length=200, unique=True)
    replacement = models.CharField(max_length=200)

    class Meta:
        """Settings for the model."""

        verbose_name_plural = "aliases"

    def __str__(self):
        """Provide string representation."""
        return "{0:s} -> {1:s}".format(self.pattern, self.replacement)

    def replace(self, what):
        """Match the regex and replace with the command."""
        command = None
        if re.search(self.pattern, what, flags=re.IGNORECASE):
            command = re.sub(self.pattern, self.replacement, what, flags=re.IGNORECASE)

        return command


class BotUser(models.Model):
    """Configure bot users, which can do things through the bot and standard Django auth."""

    nickmask = models.CharField(max_length=200, unique=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    class Meta:
        """Settings for the model."""

        permissions = (
            ('quit_bot', "Can tell the bot to quit via IRC"),
        )

    def __str__(self):
        """Provide string representation."""
        return "{0:s} (Django user {1:s})".format(self.nickmask, self.user.username)


class IrcServer(models.Model):
    """Contain server information in an object, and help contextualize channels."""

    name = models.CharField(max_length=200, unique=True)
    hostname = models.CharField(max_length=200)
    port = models.PositiveSmallIntegerField(default=6667)
    password = models.CharField(max_length=200, default=None, null=True, blank=True)

    nickname = models.CharField(max_length=32)
    realname = models.CharField(max_length=32, default='', blank=True)
    additional_addressed_nicks = models.TextField(default='', blank=True,
                                                  help_text="For e.g. BitlBee alternative nicks")

    use_ssl = models.BooleanField(default=False)
    use_ipv6 = models.BooleanField(default=False)

    post_connect = models.TextField(default='', blank=True)
    delay_before_joins = models.PositiveSmallIntegerField(default=0)

    xmlrpc_host = models.CharField(max_length=200, default='localhost')
    xmlrpc_port = models.PositiveSmallIntegerField(default=13132)

    replace_irc_control_with_markdown = models.BooleanField(default=False)

    def __str__(self):
        """Provide string summary of the server."""
        return f"{self.name} ({self.hostname}/{self.port})"


class IrcChannel(models.Model):
    """Track channel settings."""

    name = LowerCaseCharField(max_length=200)
    server = models.ForeignKey('IrcServer', on_delete=models.CASCADE)
    autojoin = models.BooleanField(default=False)

    topic_msg = models.TextField(default='', blank=True)
    topic_time = models.DateTimeField(default=timezone.now)
    topic_by = models.CharField(max_length=200, default='', blank=True)

    markov_learn_from_channel = models.BooleanField(default=True)

    discord_bridge = models.CharField(default='', max_length=32, blank=True)

    class Meta:
        """Settings for the model."""

        constraints = (
            models.UniqueConstraint(fields=['name', 'server'], name='unique_server_channel'),
        )
        permissions = (
            ('manage_current_channels', "Can join/part channels via IRC"),
        )

    def __str__(self):
        """Provide string representation."""
        return "{0:s} on {1:s}".format(self.name, self.server.name)


class IrcPlugin(models.Model):
    """Represent an IRC plugin and its loading settings."""

    path = models.CharField(max_length=200, unique=True)
    autoload = models.BooleanField(default=False)

    class Meta:
        """Settings for the model."""

        ordering = ['path']
        permissions = (
            ('manage_loaded_plugins', "Can load/unload plugins via IRC"),
        )

    def __str__(self):
        """Provide string representation."""
        return "{0:s}".format(self.path)