from django.db import models
#from django.contrib.postgres.fields import JSONField
from jsonfield import JSONField
from django.forms import ModelForm, HiddenInput
from django.contrib.auth.models import User, Group
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _ # _() this function is for print string
from django.utils import timezone
from django.contrib.auth.signals import user_logged_in

from django.contrib.sessions.models import Session
from django.conf import settings

# Create your models here.

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    colorBlind = models.BooleanField(default=False)
    group = models.ForeignKey(Group, blank=True, null=True, on_delete=models.PROTECT)
    is_disclaimer_agreed = models.BooleanField(default=False, verbose_name="Disclaimer Agreed")

    def __str__(self):  # __unicode__ for Python 2
        return self.user.username

class UserSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    session = models.OneToOneField(Session, on_delete=models.CASCADE)

class CookSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    tokenBrowser = models.CharField(max_length=1000 ,default='None')

basemapNameValidator = RegexValidator(r'^[A-Z][a-zA-Z0-9 ]*$',
                                      'Must start with A-Z and contain only letters, numbers and space.')
cartoOverlayNameValidator = RegexValidator(r'^[A-Z][a-zA-Z0-9 ]*$',
                                      'Must start with A-Z and contain only letters, numbers and space.')

class PopUpAlert(models.Model):
    start = models.DateTimeField(blank=True, null=True)
    end   = models.DateTimeField(blank=True, null=True)
    title = models.CharField(max_length=50)
    msg   = models.CharField(max_length=1000)
    
    def __str__(self):
        return self.title + self.msg[:25]

class Folder(models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(editable=False, default=timezone.now())

    def save(self, *args, **kwargs):
        if not self.id:
            self.created = timezone.now()
        return super(Folder, self).save(*args, **kwargs)
    
    def __str__(self):
        return self.name + " (%s)" % self.owner.username

class PinIcon(models.Model):
    class Meta:
        verbose_name_plural = "Pin icons"
    name = models.CharField(max_length=100)
    icon = models.ImageField(upload_to='icons')

    def __str__(self):
        return self.name

class Category(models.Model):
    class Meta:
        verbose_name        = "custom category"
        verbose_name_plural = "Custom Categories"
    name = models.CharField(max_length=100)
    pin_icon = models.ForeignKey(PinIcon,
                                blank=False,
                                null=False,
                                on_delete=models.PROTECT,
                                default=1
                                )
    owner = models.ForeignKey(User,
                                on_delete=models.CASCADE,
                                blank=True,
                                null=True
                                )
    def __str__(self):
        return self.name

class Point(models.Model):
    category  = models.ForeignKey(Category,
                                  on_delete=models.SET_NULL,
                                  blank=True,
                                  null=True,
                                 ) # was called "type" in mongodb
    location  = models.CharField(max_length=280, verbose_name='property') # address string
    address = models.CharField(max_length=280, blank=True, null=True)
    active    = models.BooleanField(default=False)
    user      = models.ForeignKey(User, on_delete=models.CASCADE)
    latitude  = models.FloatField()
    longitude = models.FloatField()
    visible   = models.BooleanField(default=True)
    circleVisible = models.BooleanField(default=False)
    circleVisible1 = models.BooleanField(default=False)
    circleVisible2 = models.BooleanField(default=False)
    folder    = models.ForeignKey(Folder,
                                  on_delete=models.SET_NULL,
                                  blank=True,
                                  null=True,
                                 )
    
#    def clean(self, *args, **kwargs):
##        cleaned_data = super().clean()
##        folder = cleaned_data.get("folder")
##        user = cleaned_data.get("user")
#        folder = folder
#        user = user
#        if folder and user:
#            if folder.owner != user:
#                raise ValidationError('Folder owner not point owner',
#                                      code='wrong user'
#                                     )
    
    def __str__(self):
        return self.location
    
    class Meta:
        verbose_name        = "property"
        verbose_name_plural = "properties"

class PointForm(ModelForm):
    class Meta:
        model = Point
        fields = ['location', 'latitude', 'longitude', 'address']
        labels = {
            'location': _('Property Name'),
        }
        widgets = {'latitude': HiddenInput(), 'longitude': HiddenInput(), 'address': HiddenInput()}

    def __init__(self, *args, **kwargs):
        super(PointForm, self).__init__(*args, **kwargs)
        self.fields['location'].widget.attrs['placeholder'] = 'Please enter Name/Alias of Property'
        self.fields['location'].widget.attrs['disabled'] = True

class Company(models.Model):
    class Meta:
        verbose_name_plural = "companies"
    name     = models.CharField(max_length=280) # e.g. REIndicator
    tag_ling = models.CharField(max_length=280) # Disconver Emerging...
    address  = models.CharField(max_length=140)
    city     = models.CharField(max_length=140)
    state    = models.CharField(max_length=20)
    country  = models.CharField(max_length=20)
    phone    = models.CharField(max_length=20)
    email    = models.EmailField()

class AccessToken(models.Model):
    name  = models.CharField(max_length=280)
    token = models.CharField(max_length=280)
    def __str__(self):
        return self.name

class Basemap(models.Model):
    name    = models.CharField(max_length=40,
                               validators=[basemapNameValidator],
                               unique=True)
    tileURL = models.CharField(max_length=280)
    default = models.BooleanField(default=False)
    def __str__(self):
        return self.name

class CartoOverlay(models.Model):
    name        = models.CharField(max_length=40,
                                   validators=[cartoOverlayNameValidator],
                                   unique=True)
    vizKey      = models.CharField(max_length=280)
    primary     = models.BooleanField(default=False)
    legendTitle = models.CharField(max_length=40, default='')
    legendData  = JSONField()
    def __str__(self):
        return self.name

def do_stuff_when_logged_in(sender, user, request, **kwargs):
    if not hasattr(user, 'profile'):
        Profile.objects.create(user=user)
        user.profile.save()
    
    if user.is_superuser:
        user.groups.clear()
        user.profile.group = None

    elif user.groups.filter(name='Both_Anticipator').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Both_Anticipator'))
        user.profile.group = Group.objects.get(name='Both_Anticipator')

    elif user.groups.filter(name='Both_Analyzer').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Both_Analyzer'))
        user.profile.group = Group.objects.get(name='Both_Analyzer')

    elif user.groups.filter(name='Both_Snapshots').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Both_Snapshots'))
        user.profile.group = Group.objects.get(name='Both_Snapshots')

    elif user.groups.filter(name='Multi_Anticipator').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Multi_Anticipator'))
        user.profile.group = Group.objects.get(name='Multi_Anticipator')

    elif user.groups.filter(name='Multi_Analyzer').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Multi_Analyzer'))
        user.profile.group = Group.objects.get(name='Multi_Analyzer')

    elif user.groups.filter(name='Multi_Snapshots').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Multi_Snapshots'))
        user.profile.group = Group.objects.get(name='Multi_Snapshots')

    elif user.groups.filter(name='Single_Anticipator').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Single_Anticipator'))
        user.profile.group = Group.objects.get(name='Single_Anticipator')

    elif user.groups.filter(name='Single_Analyzer').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Single_Analyzer'))
        user.profile.group = Group.objects.get(name='Single_Analyzer')

    elif user.groups.filter(name='Single_Snapshots').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Single_Snapshots'))
        user.profile.group = Group.objects.get(name='Single_Snapshots')

    elif user.groups.filter(name='MDM1').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='MDM1'))
        user.profile.group = Group.objects.get(name='MDM1')

    elif user.groups.filter(name='Hiatus').exists():
        user.groups.clear()
        user.groups.add(Group.objects.get(name='Hiatus'))
        user.profile.group = Group.objects.get(name='Hiatus')
    
    if not user.profile.group:
        user.groups.clear()

user_logged_in.connect(do_stuff_when_logged_in)

@receiver(models.signals.post_save, sender=User)
def post_save_user_signal_handler(sender, instance, created, **kwargs):
    if created:
        instance.is_staff = True
        instance.save()

@receiver(models.signals.post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if not hasattr(instance, 'profile'):
        Profile.objects.create(user=instance)
    instance.profile.save()

    # Setting groups with the group in profile when saving
    group_list = list(instance.groups.values_list('name',flat = True))
    if instance.profile.group:
        if not instance.groups.filter(name=instance.profile.group).exists() or len(group_list) != 1:
            instance.groups.clear()
            instance.groups.add(Group.objects.get(name=instance.profile.group))
            instance.save()
    else :
        if len(group_list) != 0:
            instance.groups.clear()
            instance.save()