from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from . import managers
from django.utils import timezone
from django.contrib.auth.models import User


SEASONS = (
    ('Spring', 'Spring'),
    ('Summer', 'Summer'),
    ('Fall', 'Fall')
)

#class MyModel(models.Model):
    # Relations
    # Attributes - Mandatory
    # Attributes - Optional
    # Object Manager
    # Custom Properties
    # Methods
    # Meta and String    

class ExecUser(models.Model):    
    user = models.OneToOneField(
        User,
        related_name = "exec_user")
    #name = user.username
    objects = managers.ExecUserManager()

class SiteAdminUser(models.Model):
    objects = managers.SiteAdminUserManager()
    #name = user.username
    user = models.OneToOneField(
        User,
        related_name = "site_admin")

class Semester(models.Model):
    afx_exec = models.OneToOneField(
        ExecUser,
        related_name = "semester"
        )

    season = models.CharField(max_length=6, choices=SEASONS)
    year = models.PositiveIntegerField()

    onProjects = True
    all_locked = False
    objects = managers.SemesterManager()

    def check_all(self):
        for t in self.teams.all():
            if t.currently_choosing_dancers():
                self.all_locked = False
                return False
        for d in self.dancers.all():
            if not d.check_dancer():
                self.all_locked = False
                return False
        self.all_locked = True
        return True

    def check_projects(self):
        for t in self.teams.all():
            if t.level=='P':
                if t.currently_choosing_dancers():
                    self.onProjects = True
                    return False
        self.onProjects = False
        return True
    
    class Meta:
        verbose_name = _("Semester")
        verbose_name_plural = _("Semesters")
        # ordering = ("user",)

    def create_dancer(self, phone, email, name, gender):
        if not self.objects.dancer_exists(email):
            return managers.DancerManager.create_dancer(self, phone, email, name, gender)
        return False

    def __str__(self):
        return ("AFX " + self.season + " " + str(self.year))

    def create_casting_group(self, dancers):
        return manager.CastingGroupManager.create_casting_group(self, dancers)

    def create_director(self, username, team, email, password):
        return manager.DirectorUserManager.create_director(username, email, password, team)

    def create_team(self, level, name):
        return manager.TeamManager.create_team(level, name, self)

class CastingGroup(models.Model):
    semester = models.ForeignKey(
        Semester,
        related_name="castingGroups",
        null=True
    )
    video_link = models.URLField(blank=True)

    objects = managers.CastingGroupManager()

    class Meta:
        verbose_name = _("Casting Group")
        verbose_name_plural = _("Casting Groups")
        # ordering = ("user",)
 
    def __str__(self):
        return str(self.id)

    def add_video_link(self, url):
        #standardize youtube links
        self.video_link = url


class Dancer(models.Model):

    casting_group = models.ForeignKey(
        CastingGroup,
        related_name = "dancers",
        blank=True,
        null=True
    )
    semester = models.ForeignKey(
        Semester,
        blank=0,
        related_name="dancers",
        )
    GENDERS = (
        ('F', 'Female'),
        ('M', 'Male')
    )

    phone = models.CharField(max_length=20, default="")
    email = models.CharField(max_length=100, default="")
    name = models.CharField(max_length=50)
    gender = models.CharField(max_length=1, choices=GENDERS)
    num_project_claims = 0
    num_training_claims = 0
    auditioned = False
    eligible = False

    objects = managers.DancerManager()

    @property
    def claims(self):
        return self.teams.all()

    @property
    def eligibleProjects(self):
        return self.auditioned

    @property
    def eligibleTraining(self):
        return auditioned and (num_project_claims < 2)

    def check_dancer(self):
        if auditioned:
            num_claims = num_project_claims + num_training_claims
            return (num_claims == 1 or num_claims == 2)
        else:
            return (num_project_claims==0 and num_training_claims==0)

    @property
    def disputed(self):
        if num_project_claims + num_training_claims > 2:
            return True
        else:
            return False

    def get_num_offers(self):
        return (num_project_claims, num_training_claims)

    @property
    def needs_team(self):
        if not auditioned:
            return False
        else:
            if num_project_claims+num_training_claims > 0:
                return False
            else:
                return True

    # @property
    # def csv_row(self):
    #     teams = ""
    #     for t in self.team_offers:
    #         teams += t.name + ","
    #     if teams=="":
    #         teams = "(No team offers)"
    #     if self.casting_group != None:
    #         row = [self.id, self.name, self.gender, self.phone, self.email, self.casting_group.id, teams]
    #     else:
    #         row = [self.id, self.name, self.gender, self.phone, self.email, "(No casting group)", teams]
    #     row = list([str(i) for i in row])
    #     return row

    class Meta:
        verbose_name = _("Dancer")
        verbose_name_plural = _("Dancers")
 
    def __str__(self):
        return self.name


class Team(models.Model):

    semester = models.ForeignKey(
        Semester,
        blank=0,
        related_name="teams",
        )

    LEVELS = (
        ('T', 'Training'),
        ('P', 'Projects')
    )

    level = models.CharField(max_length=1, choices=LEVELS)
    name = models.CharField(max_length=50)
    team_size = 0
    f_count = 0
    m_count = 0
    size_limit = models.PositiveIntegerField()
    locked = models.BooleanField()
    dancers = models.ManyToManyField(
        Dancer,
        blank = True,
        related_name="teams",
        )

    objects = managers.TeamManager()

    class Meta:
        verbose_name = _("Team")
        verbose_name_plural = _("Teams")
        # ordering = ("user",)
 
    def __str__(self):
        return self.name

    @property
    def size_limit(self):
        if self.level=='T':
            return 15
        else:
            return float('inf')

    @property
    def gender_ratio(self):   
        total = self.f_count + self.m_count     
        return (self.f_count*1.0/total, self.m_count*1.0/total)

    @property
    def reached_limit(self):
        return (self.team_size >= self.size_limit)

    @property
    def team_directors(self):
        return self.directors.all()

    def check_team(self):
        d = self.dancers.all()
        for d in dancers:
            if d.disputed:
                if self.level == 'P':
                    if d.num_project_claims > 2:
                        return False
                elif self.level == 'T':
                    return False
        return True

    def addDancer(self, dancer):
        if not self.reached_limit:
            self.dancers.add(dancer)
            if dancer.gender == 'F':
                self.f_count += 1
            elif dancer.gender== 'M':
                self.m_count += 1
            if self.level == 'T':
                dancer.num_training_claims += 1
            elif self.level == 'P':
                dancer.num_project_claims += 1
            team_size += 1

    def removeDancer(self, dancer):
        if dancer in self.dancers:
            self.dancers.remove(dancer)
            if dancer.gender == 'F':
                self.f_count -= 1
            elif dancer.gender == 'M':
                self.m_count -= 1
            if self.level == 'T':
                dancer.num_training_claims -= 1
            elif self.level == 'P':
                dancer.num_project_claims -= 1
            team_size -= 1

    #true if successful
    #false otherwise
    def lockTeam(self):
        if self.currently_choosing_dancers:
            if self.check_team:
                if not self.locked:
                    self.locked = True
                    if t.level == 'P':
                        self.semester.check_projects()
                    elif t.level == 'T':
                        self.semester.check_all()
                    return True
        return False

    def unlockTeam(self):
        if self.locked:
            self.locked = False
            if t.level == 'P':
                self.semester.onProjects = True
            elif t.level == 'T':
                self.semester.all_locked = False
            return True
        return False

    def currently_choosing_dancers(self):
        if not self.check_team:
            self.unlockTeam()
        if self.level == 'T':
            if semester.onProjects or self.locked:
                return False
        elif self.level == 'P':
            if semester.onProjects and not self.locked:
                return True

class DirectorUser(models.Model):
    user = models.OneToOneField(
        User,
        related_name="director"
    )
    #name = user.username
    team = models.ForeignKey(
        Team,
        related_name="directors"
    )
    objects = managers.DirectorUserManager()



    






