# -*- coding: utf-8 -*-

from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import calendar

from django.db import models
from django.contrib.auth.models import User
from django.template import loader, Context
from django.core import mail
from django.conf import settings
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible


def render_template(template_name, data):
    tmpl = loader.get_template(template_name)
    ctxt = Context(data)
    return tmpl.render(ctxt)


@python_2_unicode_compatible
class Tirage(models.Model):
    title = models.CharField("Titre", max_length=300)
    ouverture = models.DateTimeField("Date et heure d'ouverture du tirage")
    fermeture = models.DateTimeField("Date et heure de fermerture du tirage")
    token = models.TextField("Graine du tirage", blank=True)
    active = models.BooleanField("Tirage actif", default=False)

    def date_no_seconds(self):
        return self.fermeture.strftime('%d %b %Y %H:%M')

    def __str__(self):
        return "%s - %s" % (self.title, self.date_no_seconds())


@python_2_unicode_compatible
class Salle(models.Model):
    name = models.CharField("Nom", max_length=300)
    address = models.TextField("Adresse")

    def __str__(self):
        return self.name


@python_2_unicode_compatible
class Spectacle(models.Model):
    title = models.CharField("Titre", max_length=300)
    date = models.DateTimeField("Date & heure")
    location = models.ForeignKey(Salle)
    description = models.TextField("Description", blank=True)
    slots_description = models.TextField("Description des places", blank=True)
    price = models.FloatField("Prix d'une place")
    slots = models.IntegerField("Places")
    priority = models.IntegerField("Priorité", default=1000)
    tirage = models.ForeignKey(Tirage)
    listing = models.BooleanField("Les places sont sur listing")
    rappel_sent = models.DateTimeField("Mail de rappel envoyé", blank=True,
                                       null=True)

    class Meta:
        verbose_name = "Spectacle"
        ordering = ("priority", "date", "title",)

    def __repr__(self):
        return "[%s]" % self

    def timestamp(self):
        return "%d" % calendar.timegm(self.date.utctimetuple())

    def date_no_seconds(self):
        return self.date.strftime('%d %b %Y %H:%M')

    def __str__(self):
        return "%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(),
                                        self.location, self.price)

    def send_rappel(self):
        # On récupère la liste des participants
        members = {}
        for attr in Attribution.objects.filter(spectacle=self).all():
            member = attr.participant.user
            if member.id in members:
                members[member.id].nb_attr = 2
            else:
                member.nb_attr = 1
                members[member.id] = member
        # On écrit un mail personnalisé à chaque participant
        mails_to_send = []
        mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(),
                                        self.location)
        for member in members.values():
            mail_body = render_template('mail-rappel.txt', {
                    'member': member,
                    'show': self})
            mail_tot = mail.EmailMessage(
                    mail_object, mail_body,
                    settings.RAPPEL_FROM, [member.email],
                    [], headers={'Reply-To': settings.RAPPEL_REPLY_TO})
            mails_to_send.append(mail_tot)
        # On envoie les mails
        connection = mail.get_connection()
        connection.send_messages(mails_to_send)
        # On enregistre le fait que l'envoi a bien eu lieu
        self.rappel_sent = timezone.now()
        self.save()
        # On renvoie la liste des destinataires
        return members.values()

PAYMENT_TYPES = (
    ("cash", "Cash"),
    ("cb", "CB"),
    ("cheque", "Chèque"),
    ("autre", "Autre"),
)


@python_2_unicode_compatible
class Participant(models.Model):
    user = models.ForeignKey(User)
    choices = models.ManyToManyField(Spectacle,
                                     through="ChoixSpectacle",
                                     related_name="chosen_by")
    attributions = models.ManyToManyField(Spectacle,
                                          through="Attribution",
                                          related_name="attributed_to")
    paid = models.BooleanField("A payé", default=False)
    paymenttype = models.CharField("Moyen de paiement",
                                   max_length=6, choices=PAYMENT_TYPES,
                                   blank=True)
    tirage = models.ForeignKey(Tirage)

    def __str__(self):
        return "%s - %s" % (self.user, self.tirage.title)

DOUBLE_CHOICES = (
    ("1", "1 place"),
    ("autoquit", "2 places si possible, 1 sinon"),
    ("double", "2 places sinon rien"),
)


@python_2_unicode_compatible
class ChoixSpectacle(models.Model):
    participant = models.ForeignKey(Participant)
    spectacle = models.ForeignKey(Spectacle, related_name="participants")
    priority = models.PositiveIntegerField("Priorité")
    double_choice = models.CharField("Nombre de places",
                                     default="1", choices=DOUBLE_CHOICES,
                                     max_length=10)

    def get_double(self):
        return self.double_choice != "1"
    double = property(get_double)

    def get_autoquit(self):
        return self.double_choice == "autoquit"
    autoquit = property(get_autoquit)

    def __str__(self):
        return "Vœux de %s pour %s" % (
                self.participant.user.get_full_name,
                self.spectacle.title)

    class Meta:
        ordering = ("priority",)
        unique_together = (("participant", "spectacle",),)
        verbose_name = "voeu"
        verbose_name_plural = "voeux"


@python_2_unicode_compatible
class Attribution(models.Model):
    participant = models.ForeignKey(Participant)
    spectacle = models.ForeignKey(Spectacle, related_name="attribues")
    given = models.BooleanField("Donnée", default=False)

    def __str__(self):
        return "%s -- %s" % (self.participant, self.spectacle)
