
from django.db import models
from app.models import ItfModel
from django.contrib.auth.models import User
from datetime import datetime
from django.contrib.localflavor.in_.forms import INZipCodeField
#from ox.django.fields import DictField
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
#from imagestore.models import Album

# mail imports
from django.core.mail import send_mail
from django.template.loader import get_template
from django.template import Context
from itf.settings import SITE_HOST, DEFAULT_FROM_MAIL
from mediagallery.models import GalleryAlbum

GENDER_CHOICES = (
  ('M', 'Male'),
  ('F', 'Female'),
  ('O', 'Other'),
)


class Person(ItfModel):
    #ItfModel stuff:
    form_names = ['PersonForm', 'PopupPersonForm']
    fts_fields = ['first_name', 'last_name', 'email', 'about']
    #Basic Info
    user = models.OneToOneField(User, blank=True, null=True, db_index=True, editable=False)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    email = models.EmailField(blank=True, null=True, unique=True, db_index=True)
    tel_no = models.CharField(max_length=100, blank=True, verbose_name='Telephone number')
    is_practitioner = models.BooleanField(default=False, verbose_name='Are you a theatre practitioner?')
    is_freelancer = models.BooleanField(default=False, verbose_name='Are you a theatre associate?') #Change to is_associate
    is_enthusiast = models.BooleanField(default=True, verbose_name='Are you a theatre enthusiast?')

    about = models.TextField(blank=True, null=True, verbose_name='About yourself')
    dob = models.DateField(null=True, verbose_name="Date of Birth", blank=True)

#Occupation info
    occupations = models.ManyToManyField("Occupation", through='PersonOccupation', blank=True, null=True)
  
#Personal info
    gender = models.CharField(max_length=255, choices=GENDER_CHOICES, blank=True)
    image = models.ImageField(upload_to='images/', blank=True, null=True)
#    locations = models.ManyToManyField("Location", blank=True, null=True)  
    locations = generic.GenericRelation("Location") 
#Groups and Connections
    groups = models.ManyToManyField("TheatreGroup", blank=True, null=True, through='PersonGroup')
    connections = models.ManyToManyField('Person', blank=True, null=True, through='PersonPerson')
    productions = models.ManyToManyField("Production", blank=True, null=True, through='PersonProduction')
    trainings = generic.GenericRelation("Training", related_name='Trainee')
#    awards = models.ManyToManyField("Award", blank=True, null=True)
    languages = models.ManyToManyField("Language", blank=True, null=True) #s added
    awards = generic.GenericRelation("Award")
    buzzitems = generic.GenericRelation("BuzzItem")
    resources = generic.GenericRelation("Resource")
    galleries = generic.GenericRelation(GalleryAlbum)
#   photos = models.ManyToManyField("PhotoAlbum", blank=True, null=True)
#   orphans = models.ManyToManyField("Orphan", blank=True, null=True, through='PersonOrphan')

#Meta
    last_accessed = models.DateTimeField(default=datetime.now)

#Tokens
#    reset_token = models.CharField(max_length=256, null=True, editable=False) #s remove these tokens from here
#    validate_token = models.CharField(max_length=256, null=True, editable=False)


    def __unicode__(self):
        return "%s %s" % (self.first_name, self.last_name,)
        
    def get_title(self):
        return self.__unicode__()

    def get_dict(self):
        #lconnections = [obj for obj in self.connections.all()]
        #rconnections = [ obj for obj in PersonPerson.objects.filter(person2=self)
        return {
            'first_name': self.first_name,
            'last_name': self.last_name,
            'about': self.about,
            'tel_no': self.tel_no,
            'about':self.about,
            'dob':self.dob,
            'is_practitioner':self.is_practitioner,
            'is_enthusiast':self.is_enthusiast,
            'is_freelancer': self.is_freelancer,
            'occupations': [ obj for obj in self.occupations.all()],
            'gender':self.gender,
            'image':self.image,
            'languages': [obj for obj in self.languages.all()],
            'locations': [obj for obj in self.locations.all()],
            'groups':  [obj for obj in self.persongroup_set.all()],
            'connections': [obj for obj in self.PersonFrom.all()]  + [obj for obj in self.PersonTo.all() ],
            'productions': [ obj for obj in self.personproduction_set.all()],
            'trainings': [ obj for obj in self.trainings.all()],
            'languages': [ obj for obj in self.languages.all()],
            'awards':  [ obj for obj in self.awards.all()],
            'buzzitems': [ obj for obj in self.buzzitems.all()],
            'resources': self.resources.all(),
            'related_scripts': self.related_scripts()
            }

    def related_scripts(self):
        prod_scripts = [ p.script for p in self.productions.all() ]
        prod_scripts.extend( [ p.script for p in self.productions_authored.all() ] )
        prod_scripts.extend( [ p.script for p in self.productions_directed.all() ] )        
        #auth_scripts = Script.objects.filter(author__iexact=)
        return prod_scripts



OCCUPATION_TYPES = (
    ('practitioner', 'Practitioner'),
    ('associate', 'Associate'),
)

class Occupation(models.Model):
    name = models.CharField(max_length=255)
    occupation_type = models.CharField(choices=OCCUPATION_TYPES, max_length=64)
    extra_text = models.BooleanField(default=False)    

    def __unicode__(self):
        return self.name

    def is_child(self):
        return self.parent != None

    def is_parent(self):
        if self.is_child():
            return False
        else:
            if Occupation.objects.filter(parent=self).count() > 0: #self has children
                return True
        return False

BUZZ_ITEM_TYPES = (
    ('review', 'Review'),
    ('publicity', 'Publicity'),
)


class PersonInvitation(models.Model):
    invite_code = models.CharField(max_length=30)
    inviter = models.ForeignKey(Person, related_name='has_invited', null=True, blank=True)
    invitee = models.ForeignKey(Person, related_name='was_invited_by', null=True, blank=True)
    is_validated=models.BooleanField(default=False)
    sent_date = models.DateTimeField()

    def send_invite(self):
        #import pdb ; pdb.set_trace()
        from django.core.mail import send_mail
        from django.template.loader import get_template
        from django.template import Context
        from itf.settings import SITE_HOST, DEFAULT_FROM_MAIL 

        template = get_template('modules/itfprofiles/invitation_email.txt')
        subject = 'Invitation to join the India Theatre Forum'


        link = 'http://%s/invitation/accept/%s/' % ( SITE_HOST, self.invite_code, )

        context = Context({
                'name': str(self.invitee.first_name) + ' ' + str(self.invitee.last_name),
                'link': link,
                'sender': str(self.inviter.first_name) + ' ' + str(self.inviter.last_name) 
                })
        message = template.render(context)        
        send_mail(
            subject, message,
            DEFAULT_FROM_MAIL, [self.invitee.email]
            )

    
    def __unicode__(self):
        return u'%s, %s' % (self.invitee.first_name, self.invitee.email)



class BuzzItem(ItfModel):
    link = models.URLField(verify_exists=False)
    title = models.CharField(max_length=255)
    blurb = models.TextField(blank=True)
    typ = models.CharField(choices=BUZZ_ITEM_TYPES, max_length=128, blank=True, verbose_name="Type")
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
   
    def __unicode__(self):
        return self.title
   

STATE_CHOICES= (
         ('0', 'Andaman and Nicobar'),
          ('1', 'Andhra Pradesh'),
          ('2', 'Arunachal Pradesh'),
          ('3', 'Asom (Assam)'),
          ('4', 'Bihar'),
          ('5', 'Chandigarh'),
          ('6', 'Chhattisgarh'),
          ('7', 'Dadra and Nagar Haveli'),
          ('8', 'Daman and Diu'),
          ('9', 'Delhi'),
          ('10', 'Goa'),
          ('11', 'Gujarat'),
          ('12', 'Haryana'),
          ('13', 'Himachal Pradesh'),
          ('14', 'Jammu And Kashmir'),
          ('15', 'Jharkhand'),
          ('16', 'Karnataka'),
          ('17', 'Kerala'),
          ('18', 'Lakshadweep'),
          ('19', 'Madhya Pradesh'),
          ('20', 'Maharashtra'),
          ('21', 'Manipur'),
          ('22', 'Meghalaya'),
          ('23', 'Mizoram'),
          ('24', 'Nagaland'),
          ('25', 'Odisha(Orrisa)'),
          ('26', 'Pondicherry'),
          ('27', 'Punjab'),
          ('28', 'Rajasthan'),
          ('29', 'Sikkim'),
          ('30', 'Tamilnadu'),
          ('31', 'Tripura'),
          ('32', 'Uttarakhand (Uttaranchal)'),
          ('33', 'Uttar Pradesh'),
          ('34', 'West Bengal'),
          ('35', 'Not Applicable'),
)

class City(models.Model):
    name  = models.CharField(max_length=255)
    state = models.CharField(choices = STATE_CHOICES, max_length=255)

    def __unicode__(self):
        return self.name 

from django.contrib.localflavor.in_.forms import INZipCodeField
class Location(models.Model):
    #lat= models.FloatField(blank=True, null=True)
    #lon= models.FloatField(blank=True, null=True)
    city = models.ForeignKey(City)
    pincode= INZipCodeField() 
    address= models.TextField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

class PersonOccupation(models.Model):
    person = models.ForeignKey(Person, db_index=True)
    occupation = models.ForeignKey(Occupation)
    is_main = models.BooleanField(default=False, verbose_name='Is this your main occupation?')
#    order = models.IntegerField()


class PersonPerson(models.Model):
    person1 = models.ForeignKey(Person, related_name='PersonFrom', db_index=True)
    person2 = models.ForeignKey(Person, related_name='PersonTo', db_index=True, verbose_name='connection')
    relation = models.ForeignKey("Relation")
    disapproved = models.BooleanField(default=False)


class Relation(models.Model):
    name = models.CharField(max_length=255, db_index=True)
    reverse = models.CharField(max_length=255, db_index=True)

    def __unicode__(self):
        return self.name


class Training(models.Model):
    # title = models.CharField(max_length=255)
    # desc= models.TextField(max_length=2048)
    person = models.ForeignKey("Person")
    area = models.CharField(max_length=255) 
    with_whom = models.CharField(max_length=255) # Is this a foreign key to person, or group, or just text field like now?
    #trained_by=models.ManyToManyField('Person', related_name='trained')
    where = models.ForeignKey("TheatreGroup")
    from_when = models.DateField(blank=True, null=True)
    until_when = models.DateField(blank=True, null=True)
    locations = generic.GenericRelation("Location")
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.area


class Play(ItfModel):
    title = models.CharField(max_length=512)
    author = models.CharField(max_length=512, blank=True)
    year = models.IntegerField(null=True, blank=True, max_length=4)    
    added_by = models.ForeignKey(User)
    
    def __unicode__(self):
        return self.title

class TheatreGroup(ItfModel):
    fts_fields = ['name', 'about']
    form_names = ['TheatreGroupForm', 'PopupGroupForm']
    main_form = 'TheatreGroupForm'
    added_by = models.ForeignKey(User)
    name = models.CharField(max_length=255, db_index=True, help_text='Name of theatre group') # name + location is unique
    email = models.EmailField(blank=True, null=True)
#    location = models.ForeignKey(Location, blank=True, null=True, related_name="theatregroup_location")
    tel = models.IntegerField(blank=True, null=True, verbose_name='Telephone number')
     # -- FIXME tel = models.CharField(blank=True, null=True)

    #image = models.ImageField(upload_to='upload/groups/', blank=True)
    languages = models.ManyToManyField("Language", blank=True, null=True)
    year_founded = models.IntegerField(blank=True, null=True)
    about = models.TextField(blank=True)
    awards = generic.GenericRelation("Award")
    buzzitems = generic.GenericRelation("BuzzItem")
    galleries = generic.GenericRelation(GalleryAlbum)

    website = models.URLField(blank=True, verify_exists=False)
    resources = generic.GenericRelation("Resource")
    locations = generic.GenericRelation("Location")
#    albums = generic.GenericRelation(Album)
    nature_of_work = models.ManyToManyField("GroupOccupation", blank=True, null=True, through="GroupGroupOccupation")
#    locations = models.ManyToManyField("Location", blank=True, null=True, related_name="theatregroup_locations")   

    about = models.TextField(blank=True, null=True)
    #nature_of_work = models.CharField(max_length=255)
#    founded = models.CharField(max_length=10)
    trainings = generic.GenericRelation("Training")
    allow_comments = models.BooleanField('allow comments', default=True)

    def __unicode__(self):
        return self.name

    def user_has_perms(self, user):
        from app.models import ItfModel
        if ItfModel.user_has_perms(self, user):
            return True
        else:
            if self.is_user_admin(user):
                return True
            else:
                return False

    def is_user_admin(self, user):
        for pg in self.persongroup_set.all():
            if user.id == pg.person.user_id and pg.is_admin == True:
                return True
        return False      

    def get_dict(self):
        return {
            #'object':self,
            'name': self.name,
            'email': self.email,
            'tel':self.tel,
            'nature_of_work': [obj for obj in self.nature_of_work.all().order_by('groupgroupoccupation__is_main')],
            'venues': [obj for obj in self.locations.all()],
            'trainings': [obj for obj in self.training_set.all()],
            'languages': [obj.name for obj in self.languages.all()],
            #'venues': [obj for obj in self.locations],
            'founded': self.year_founded,
            'about': self.about,
            'awards': [obj for obj in self.awards.all()],
            'website': self.website,
            'resources': [obj for obj in self.resources.all()],
            'buzzitems': [obj for obj in self.buzzitems.all()],
            'productions': [obj for obj in self.production_set.all() ],
            'scripts': [obj for obj in self.script_set.all() ],
            'people' :  [obj for obj in self.persongroup_set.all() ],
            'worked_with_people': self.worked_with_people()
        }

    def worked_with_people(self):
        people =  []
        for p in self.production_set.all():
            if p.get_people():
                people.extend(p.get_people())

        #script_auths = [ {"person":s.author, "role":"author","assoc_type":'script', "assoc_name":s.title } for s in self.script_set.all() ]  
        return people 

    def get_title(self):
        return self.__unicode__()

class Resource(models.Model):
    title = models.CharField(max_length=255, blank=True)
    desc = models.TextField(max_length=10000, blank=True, null =True, help_text="Optional Description, 500 words or less")
    fil = models.FileField(upload_to='upload/docs', blank=True, null=True, verbose_name='File')
    url = models.URLField(blank=True, null=True, verify_exists=True)
    thumbnail= models.ImageField(upload_to='uploads/docs', blank=True, null=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    def get_link(self):
        if self.fil:
            return self.fil.url
        elif self.url:
            return self.url
        else:
            return False

from scriptbank.models import Script
  
class Production(ItfModel):
#    user = models.ForeignKey(User)
    fts_fields = ['name', 'synopsis', 'group__name', 'director__first_name', 'director__last_name', 'playwright__first_name', 'playwright__last_name', 'anecdotes']
    form_names = ['ProductionForm', 'PopupProductionForm']
    main_form = 'ProductionForm'
    added_by = models.ForeignKey(User)
    script = models.ForeignKey(Script, blank=True, null=True)
    name = models.CharField(max_length=255, db_index=True)
    synopsis = models.TextField(blank=True)    
    languages = models.ManyToManyField("Language", blank=True, null=True)
    group = models.ForeignKey("TheatreGroup", blank=True, null=True)
    director = models.ForeignKey(Person, related_name='productions_directed', blank=True, null=True)
    playwright = models.ForeignKey(Person, related_name='productions_authored', blank=True, null=True)
    anecdotes = models.TextField(blank=True)    
    awards = generic.GenericRelation("Award")
    debut_date = models.DateField(blank=True, null=True)
    reviews= generic.GenericRelation("BuzzItem")
    galleries = generic.GenericRelation(GalleryAlbum)
    #FIXME: add no of shows

    def __unicode__(self):
        return self.name

    def user_has_perms(self, user):
        if self.added_by_id == user.id:
            return True
        return self.group.user_has_perms(user)

    def get_people(self):
        persons = [{"person":self.director, "role":"director", "assoc_type":'production', "assoc_name":self.name }, 
                   {"person":self.playwright, "role":"playwright", "assoc_type":'production', "assoc_name":self.name }
                   ]
        cast_list=[] 
        for p in self.personproduction_set.all():
            cast_list.append({"person":p.person, "role":p.role, "assoc_type":'production', "assoc_name":self.name})
            if cast_list:
                persons.extend(cast_list)
        return persons


        
    def get_dict(self):
        from events.models import Event
        rel_level1 = [obj for obj in Production.objects.filter(script=self.script)]
        rel_level2 = list(set(obj.production_set.all() for obj in self.script.related_scripts.all()))
        shows = Event.objects.filter(production=self).order_by('-start_date')
        last_date = None
        if shows.count() > 0:
            last_date = shows[0].start_date
        return {
            'name': self.name,
            'anecdotes': self.anecdotes,
            'group': self.group,
            'director': self.director,
            'playwright': self.playwright,
            'script': self.script,
            'synopsis': self.synopsis,
            'awards': [ obj for obj in self.awards.all()],
            'shows': shows,
            'languages': [ obj for obj in self.languages.all()],    
            'debut_date':self.debut_date,
            'last_date': last_date,
            'sibling_productions': rel_level1,
            'related_productions' : rel_level2,
            'people': self.get_people()      
        }


SHOWS_NO_CHOICES = (
    ('5', '0-5 Shows'),
    ('10', '6-10 Shows'),
    ('50', '11-50 Shows'),
    ('100', '51-100 Shows'),
    ('1000', 'More Than 100 Shows'),
#add more.
)

class PersonProduction(models.Model):
    person = models.ForeignKey(Person, db_index=True)
    production = models.ForeignKey(Production, db_index=True)
    role = models.CharField(max_length=255)
    start_year = models.IntegerField(max_length=4)
    years = models.IntegerField(blank=True, null=True)
    no_of_shows = models.CharField(max_length=25, choices = SHOWS_NO_CHOICES)  
    original_cast = models.BooleanField(default=False)

    def years(self):
        if self.years:
            return str(self.start_year) + " - " + str(self.start_year + self.years)
        else:
            return str(self.start_year)                                        


class PersonGroup(models.Model):
    person = models.ForeignKey(Person, db_index=True)
    group = models.ForeignKey(TheatreGroup, db_index=True)
    is_admin = models.BooleanField(default=False)
    role = models.CharField(max_length=255, blank=True)







class Award(models.Model):
    title = models.CharField(max_length=255)
    year = models.IntegerField(blank=True)
    link = models.URLField(verify_exists=False, blank=True, null=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.title

class GroupOccupation(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class GroupGroupOccupation(models.Model):
    theatregroup = models.ForeignKey("TheatreGroup")
    groupoccupation = models.ForeignKey("GroupOccupation", verbose_name="Occupation")
    is_main = models.BooleanField(default=False, verbose_name="Is this the group's main occupation?")
    


class Language(models.Model):
    code = models.CharField(max_length=3, db_index=True)
    name = models.CharField(max_length=255)

    def __unicode__(self):
        return self.name

