from django.db import models
from django.contrib.auth.models import User as WebUser
from django.core.validators import validate_unicode_slug, MaxLengthValidator, MaxValueValidator, URLValidator

class Owner(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.CASCADE,
    )
    source = models.CharField(
        max_length=50,
        unique=True,
    )

class Network(models.Model):
    name = models.CharField(
        max_length=40,
        unique=True,
        validators=[MaxLengthValidator(40)],
    )
    slug = models.SlugField(
        db_index=True,
        unique=True,
        validators=[validate_unicode_slug],
    )
    nickname = models.CharField(
        max_length=31,
        default='RotBot',
        validators=[MaxLengthValidator(31)],
    )
    username = models.CharField(
        max_length=31,
        default='pyRot',
        validators=[MaxLengthValidator(31)],
    )
    password = models.CharField(
        null=True,
        blank=True,
        max_length=31,
        validators=[MaxLengthValidator(31)],
    )
    mail = models.EmailField()
    home_channel = models.CharField(
        max_length=64,
        default='#RotBot',
        validators=[MaxLengthValidator(64)],
    )
    command_character = models.CharField(
        max_length=1,
        default='!',
        validators=[MaxLengthValidator(1)],
    )
    help_character = models.CharField(
        max_length=1,
        default='@',
        validators=[MaxLengthValidator(1)],
    )
    enabled = models.BooleanField(
        default=True,
    )
    SERVICE_CHOICES = [
        ('m', 'Modern network services, like Rizon.'),
        ('x', 'X bot, like UnderNet.'),
        ('n', 'None, bare server.'),
    ]
    # network_services = models.CharField(
    #     max_length=1,
    #     default='m',
    #     choices=SERVICE_CHOICES,
    # )
    # mute = models.BooleanField(
    #     default=False,
    # )

    class Meta:
        ordering = ['name']

    def get_absolute_url(self):
        from django.urls import reverse
        return reverse('rotbot.views.network', args=[str(self.id)])
        # Try this in the template: <a href="{{ object.get_absolute_url }}">{{ object.name }}</a>


    def __str__(self):
        return self.name

class Host(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.CASCADE,
        related_name="host",
        related_query_name="hosts",
    )
    address = models.CharField(
        max_length=200,
        unique=True,
        validators=[MaxLengthValidator(200)],
    )
    port = models.PositiveSmallIntegerField(
        default = 6697,
        validators=[MaxValueValidator(65535)],
    )
    ssl = models.BooleanField(
        default=True,
    )
    connection_attempts = models.PositiveIntegerField(
        default=0,
    )
    connection_succeeds = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        order_with_respect_to = 'network'
        unique_together = ['address', 'port']

    @property
    def connect_string(self):
        return '%s:%s' % (self.address, self.port)

    def __str__(self):
        return '%s:%s' % (self.address, self.port)

class Channel(models.Model):
    slug = models.SlugField(
        unique=True,
        validators=[validate_unicode_slug],
    )
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
        related_name="channel",
        related_query_name="channels",
    )
    name = models.CharField(
        max_length=64,
    )
    autojoin = models.BooleanField(
        default=False,
        #null=True,
        #blank=False
    )
    key = models.CharField(
        max_length=32,
    )
    games = models.BooleanField(
        default=False,
    )
    chat = models.BooleanField(
        default=False,
    )
    statistic_commands = models.BooleanField(
        default=False,
    )
    CHANNEL_EVENT_TYPE_CHOICES = [
        #('pm', 'private message'),
        #('pa', 'private action'),
        #('pn', 'private notice'),
        ('cm', 'channel message'),
        ('ca', 'channel action'),
        ('cn', 'channel notice'),
        ('ct', 'channel topic'),
        ('ck', 'channel password'),
        ('ci', 'channel invite'),
        ('cj', 'channel join'),
        ('cp', 'channel part'),
        ('ck', 'channel kick'),
        ('kd', 'channel kicked'),
        ( 'mc', 'mode change'),
        #('nc', 'nick change'),
        #('sq', 'quit'),
    ]
    last_event_type = models.CharField(
        max_length=2,
        choices=CHANNEL_EVENT_TYPE_CHOICES,
    )
    last_event_datetime = models.DateTimeField(
        auto_now=True,
    )
    last_event_channel = models.ForeignKey(
        'Channel',
        on_delete=models.CASCADE,
        null=True,
    )
    last_event_user = models.ForeignKey(
        'User',
        on_delete=models.CASCADE,
        null=True,
    )
    last_event_subject = models.ForeignKey(
        'User',
        on_delete=models.CASCADE,
        null=True,
        related_name='channel_subject',
    )
    last_event_content = models.CharField(
        null=True,
        max_length = 307,
    )


    class Meta:
        unique_together = ['network', 'name']

    def __str__(self):
        return '%s/$s' % (self.network, self.name)

class TempChannelKey(models.Model):
    key = models.CharField(
        max_length=40,
        unique=True,
    )
    network = models.ForeignKey(
        'Network',
        on_delete=models.CASCADE,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.CASCADE,
    )
    created = models.DateTimeField(
        auto_now_add=True,
    )

class User(models.Model):
    slug = models.SlugField(
        unique=True,
        validators=[validate_unicode_slug],
    )
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    name = models.CharField(
        max_length=31
    )
    aliasses = models.ManyToManyField('self')
    USER_EVENT_TYPE_CHOICES = [
        ('pm', 'private message'),
        ('pa', 'private action'),
        ('pn', 'private notice'),
        ('cm', 'channel message'),
        ('ca', 'channel action'),
        ('cn', 'channel notice'),
        ('ct', 'channel topic'),
        ('ck', 'channel password'),
        ('ci', 'channel invite'),
        ('cj', 'channel join'),
        ('cp', 'channel part'),
        ('ck', 'channel kick'),
        ('kd', 'channel kicked'),
        ('mc', 'mode change'),
        ('nc', 'nick change'),
        ('sq', 'quit'),
    ]
    last_event_type = models.CharField(
        max_length=2,
        choices=USER_EVENT_TYPE_CHOICES,
    )
    last_event_datetime = models.DateTimeField(
        auto_now=True,
    )
    last_event_channel = models.ForeignKey(
        'Channel',
        on_delete=models.CASCADE,
        null=True,
    )
    last_event_user = models.ForeignKey(
        'User',
        on_delete=models.CASCADE,
        null=True,
    )
    last_event_subject = models.ForeignKey(
        'User',
        on_delete=models.CASCADE,
        null=True,
        related_name='user_subject',
    )
    last_event_content = models.CharField(
        null=True,
        max_length = 307,
    )
    xp_spent = models.PositiveIntegerField(
        default=0,
    )
    level = models.PositiveIntegerField(
        default=0,
    )
    coin = models.PositiveIntegerField(
        default=0,
    )
    coin_given = models.PositiveIntegerField(
        default=0,
    )
    coin_spent = models.PositiveIntegerField(
        default=0
    )
    ap_spent = models.PositiveIntegerField(
        default=0,
    )
    karma_correction = models.PositiveIntegerField(
        default=0,
    )
    no_chat = models.BooleanField(
        default=False,
    )


    class Meta:
        unique_together = ['network', 'name']

class Join(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.PROTECT,
    )
    user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
    )
    amount = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        unique_together = ['network', 'channel', 'user']

class Message(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.PROTECT,
    )
    user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
    )
    amount = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        unique_together = ['network', 'channel', 'user']

class Action(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.PROTECT,
    )
    user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
    )
    amount = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        unique_together = ['network', 'channel', 'user']

class Notice(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.PROTECT,
    )
    user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
    )
    amount = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        unique_together = ['network', 'channel', 'user']

class Kick(models.Model):
    network = models.ForeignKey(
        'Network',
        on_delete=models.PROTECT,
    )
    channel = models.ForeignKey(
        'Channel',
        on_delete=models.PROTECT,
    )
    kicker = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
        related_name='kicker',
    )
    kicked = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
        related_name='kicked',
    )
    amount = models.PositiveIntegerField(
        default=0,
    )

    class Meta:
        unique_together = ['network', 'channel', 'kicker', 'kicked']

class CurseWord(models.Model):
    word = models.CharField(
        max_length=15,
        unique=True,
    )
    created = models.DateField(
        auto_now_add=True,
    )
    irc_user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    web_user = models.ForeignKey(
        WebUser,
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    banned = models.BooleanField(
        default=False,
    )

    def __str__(self):
        return self.word

class CurseAdjective(models.Model):
    word = models.CharField(
        max_length=15,
        unique=True,
    )
    created = models.DateField(
        auto_now_add=True,
    )
    irc_user = models.ForeignKey(
        'User',
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    web_user = models.ForeignKey(
        WebUser,
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    banned = models.BooleanField(
        default=False,
    )

    def __str__(self):
        return self.word
