from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from respa_outlook.manager import store, ToEWSDateTime

from exchangelib import CalendarItem, Mailbox, Attendee, EWSTimeZone
from exchangelib.properties import Mailbox
from exchangelib.version import EXCHANGE_2016
from os.path import abspath, join
from datetime import datetime, timedelta


import time

from resources.models import Reservation
from resources.models.utils import send_respa_mail


from copy import copy

import pytz

class RespaOutlookConfigurationQuerySet(models.QuerySet):
    pass

class RespaOutlookConfiguration(models.Model):
    name = models.CharField(verbose_name=_("Configuration name"), max_length=255)
    resource = models.ForeignKey('resources.Resource', verbose_name=_('Resource'), related_name='_Resources',
                                    blank=True, null=True, on_delete=models.CASCADE)

    email = models.CharField(verbose_name=_('Email'), max_length=255)
    password = models.CharField(verbose_name=_('Password'), max_length=255)


    objects = RespaOutlookConfigurationQuerySet.as_manager()

    class Meta:
        verbose_name = _("Outlook configuration")
        verbose_name_plural = _("Outlook configurations")

    def __str__(self):
        try:
            return '%s (%s) [%s]' % (self.name, self.resource.name, self.email)
        except:
            return self.name

    def handle_create(self, reservation):
        if not reservation.reserver_email_address:
            return
        if not reservation.reserver_email_address.endswith(settings.OUTLOOK_EMAIL_DOMAIN):
            return

        unit_address = reservation.resource.unit.address_postal_full if reservation.resource.unit.address_postal_full else reservation.resource.unit.street_address

        manager = store.items.get(self.id)

        appointment = CalendarItem(
            account=manager.account,
            folder=manager.calendar,
            subject = 'Reservation created',
            body = 'You have created an reservation',
            start=ToEWSDateTime(reservation.begin),
            end=ToEWSDateTime(reservation.end),
            categories=[],
            location=unit_address,
            required_attendees=[
                Attendee(
                    mailbox=Mailbox(email_address=reservation.reserver_email_address),
                    response_type='Accept'
                )
            ]
        )
        Mailbox.get_field_by_fieldname('routing_type').supported_from = EXCHANGE_2016
        appointment.save()
        self.create_respa_outlook_reservation(appointment=appointment, reservation=reservation,
                                              email=reservation.reserver_email_address)


    def handle_modify(self, reservation, appointment=None):
        manager = store.items.get(self.id)
        outlook = RespaOutlookReservation.objects.get(reservation_id=reservation.id)

        if appointment:
            cache = copy(reservation)
            if reservation.begin != appointment.start:
                reservation.begin = appointment.start
            if reservation.end != appointment.end:
                reservation.end = appointment.end
            try:
                reservation.clean()
                reservation.save()
            except ValidationError:
                appointment.start = cache.begin
                appointment.end = cache.end
                appointment.required_attendees[0] = \
                    Attendee(
                        mailbox=Mailbox(email_address=cache.reserver_email_address),
                        response_type='Accept'
                    )
                appointment.save()
        else:
            appointment = manager.calendar.get(id=outlook.exchange_id)
            appointment.start = ToEWSDateTime(reservation.begin)
            appointment.end = ToEWSDateTime(reservation.end)

            appointment.required_attendees[0] = \
                     Attendee(
                        mailbox=Mailbox(email_address=reservation.reserver_email_address),
                        response_type='Accept'
                    )
            appointment.save()
        outlook.modified = datetime.now() + timedelta(minutes=2)
        outlook.save()



    def create_respa_outlook_reservation(self, appointment, reservation, email):
        if not appointment:
            return
        if not reservation:
            if not email:
                return
            reservation = Reservation(
                resource = self.resource,
                begin = appointment.start,
                end = appointment.end,
                reserver_email_address = email,
                state = Reservation.CONFIRMED
            )
            reservation.clean()
            reservation.save()
            ret = send_respa_mail(
                email_address=email,
                subject="Reservation created",
                body="Reservation via outlook created"
            )
            print(ret[0], ret[1])

        RespaOutlookReservation(
            name = '%s (%s)' % (reservation.reserver_email_address, self.resource.name),
            exchange_id = appointment.id,
            exchange_changekey = appointment.changekey,
            reservation = reservation
        ).save()



class RespaOutlookReservationQuerySet(models.QuerySet):
    pass

class RespaOutlookReservation(models.Model):
    name = models.CharField(verbose_name=_("Reserver name & Resource"), max_length=255)

    reservation = models.ForeignKey('resources.Reservation', verbose_name=_('Reservation'), related_name='OutlookReservations',
                                    blank=True, null=True, on_delete=models.CASCADE)

    exchange_id = models.CharField(verbose_name=_("Exchange ID"), max_length=255)
    exchange_changekey = models.CharField(verbose_name=_("Exchange Key"), max_length=255)

    modified = models.DateTimeField(verbose_name=_('Modified'), blank=True, null=True)

    objects = RespaOutlookReservationQuerySet.as_manager()

    class Meta:
        verbose_name = _("Outlook reservation")
        verbose_name_plural = _("Outlook reservations")


    def __str__(self):
        try:
            return '%s [%s-%s]' % (self.name, self.reservation.begin, self.reservation.end)
        except:
            return self.name


    def get_modified_timestamp(self):
        if self.modified:
            return int((self.modified.replace(tzinfo=pytz.timezone('Europe/Helsinki')) - datetime(year=1970, month=1, day=1, hour=0, minute=0, second=0).replace(tzinfo=pytz.timezone('Europe/Helsinki'))).total_seconds())

        #return int(time.time())
        return int((datetime.now().replace(tzinfo=None) - datetime(year=1970, month=1, day=1, hour=0, minute=0, second=0).replace(tzinfo=None)).total_seconds())


from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from respa_outlook.manager import store, ToEWSDateTime

from exchangelib import CalendarItem, Mailbox, Attendee, EWSTimeZone
from exchangelib.properties import Mailbox
from exchangelib.version import EXCHANGE_2016
from os.path import abspath, join
from datetime import datetime, timedelta


import time

from resources.models import Reservation
from resources.models.utils import send_respa_mail


from copy import copy

import pytz

class RespaOutlookConfigurationQuerySet(models.QuerySet):
    pass

class RespaOutlookConfiguration(models.Model):
    name = models.CharField(verbose_name=_("Configuration name"), max_length=255)
    resource = models.ForeignKey('resources.Resource', verbose_name=_('Resource'), related_name='_Resources',
                                    blank=True, null=True, on_delete=models.CASCADE)

    email = models.CharField(verbose_name=_('Email'), max_length=255)
    password = models.CharField(verbose_name=_('Password'), max_length=255)


    objects = RespaOutlookConfigurationQuerySet.as_manager()

    class Meta:
        verbose_name = _("Outlook configuration")
        verbose_name_plural = _("Outlook configurations")

    def __str__(self):
        try:
            return '%s (%s) [%s]' % (self.name, self.resource.name, self.email)
        except:
            return self.name

    def handle_create(self, reservation):
        if not reservation.reserver_email_address:
            return
        if not reservation.reserver_email_address.endswith(settings.OUTLOOK_EMAIL_DOMAIN):
            return

        unit_address = reservation.resource.unit.address_postal_full if reservation.resource.unit.address_postal_full else reservation.resource.unit.street_address

        manager = store.items.get(self.id)

        appointment = CalendarItem(
            account=manager.account,
            folder=manager.calendar,
            subject = 'Reservation created',
            body = 'You have created an reservation',
            start=ToEWSDateTime(reservation.begin),
            end=ToEWSDateTime(reservation.end),
            categories=[],
            location=unit_address,
            required_attendees=[
                Attendee(
                    mailbox=Mailbox(email_address=reservation.reserver_email_address),
                    response_type='Accept'
                )
            ]
        )
        Mailbox.get_field_by_fieldname('routing_type').supported_from = EXCHANGE_2016
        appointment.save()
        self.create_respa_outlook_reservation(appointment=appointment, reservation=reservation,
                                              email=reservation.reserver_email_address)


    def handle_modify(self, reservation, appointment=None):
        manager = store.items.get(self.id)
        outlook = RespaOutlookReservation.objects.get(reservation_id=reservation.id)

        if appointment:
            cache = copy(reservation)
            if reservation.begin != appointment.start:
                reservation.begin = appointment.start
            if reservation.end != appointment.end:
                reservation.end = appointment.end
            try:
                reservation.clean()
                reservation.save()
            except ValidationError:
                appointment.start = cache.begin
                appointment.end = cache.end
                appointment.required_attendees[0] = \
                    Attendee(
                        mailbox=Mailbox(email_address=cache.reserver_email_address),
                        response_type='Accept'
                    )
                appointment.save()
        else:
            appointment = manager.calendar.get(id=outlook.exchange_id)
            appointment.start = ToEWSDateTime(reservation.begin)
            appointment.end = ToEWSDateTime(reservation.end)

            appointment.required_attendees[0] = \
                     Attendee(
                        mailbox=Mailbox(email_address=reservation.reserver_email_address),
                        response_type='Accept'
                    )
            appointment.save()
        outlook.modified = datetime.now() + timedelta(minutes=2)
        outlook.save()



    def create_respa_outlook_reservation(self, appointment, reservation, email):
        if not appointment:
            return
        if not reservation:
            if not email:
                return
            reservation = Reservation(
                resource = self.resource,
                begin = appointment.start,
                end = appointment.end,
                reserver_email_address = email,
                state = Reservation.CONFIRMED
            )
            reservation.clean()
            reservation.save()
            ret = send_respa_mail(
                email_address=email,
                subject="Reservation created",
                body="Reservation via outlook created"
            )
            print(ret[0], ret[1])

        RespaOutlookReservation(
            name = '%s (%s)' % (reservation.reserver_email_address, self.resource.name),
            exchange_id = appointment.id,
            exchange_changekey = appointment.changekey,
            reservation = reservation
        ).save()



class RespaOutlookReservationQuerySet(models.QuerySet):
    pass

class RespaOutlookReservation(models.Model):
    name = models.CharField(verbose_name=_("Reserver name & Resource"), max_length=255)

    reservation = models.ForeignKey('resources.Reservation', verbose_name=_('Reservation'), related_name='OutlookReservations',
                                    blank=True, null=True, on_delete=models.CASCADE)

    exchange_id = models.CharField(verbose_name=_("Exchange ID"), max_length=255)
    exchange_changekey = models.CharField(verbose_name=_("Exchange Key"), max_length=255)

    modified = models.DateTimeField(verbose_name=_('Modified'), blank=True, null=True)

    objects = RespaOutlookReservationQuerySet.as_manager()

    class Meta:
        verbose_name = _("Outlook reservation")
        verbose_name_plural = _("Outlook reservations")


    def __str__(self):
        try:
            return '%s [%s-%s]' % (self.name, self.reservation.begin, self.reservation.end)
        except:
            return self.name


    def get_modified_timestamp(self):
        if self.modified:
            return int((self.modified.replace(tzinfo=pytz.timezone('Europe/Helsinki')) - datetime(year=1970, month=1, day=1, hour=0, minute=0, second=0).replace(tzinfo=pytz.timezone('Europe/Helsinki'))).total_seconds())

        #return int(time.time())
        return int((datetime.now().replace(tzinfo=None) - datetime(year=1970, month=1, day=1, hour=0, minute=0, second=0).replace(tzinfo=None)).total_seconds())


#return int(time.time())