# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import logging
import simple_audit
from django.db import models
from django.utils.translation import ugettext_lazy as _
from physical.models import Host
from util.models import BaseModel
from django.db.models.signals import post_save
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from celery.task.control import revoke
from .tasks import execute_scheduled_maintenance

LOG = logging.getLogger(__name__)


class Maintenance(BaseModel):
    WAITING = 0
    RUNNING = 1
    FINISHED = 2
    REJECTED = 3

    MAINTENANCE_STATUS = (
        (FINISHED, 'Finished'),
        (RUNNING, 'Running'),
        (WAITING, 'Waiting'),
        (REJECTED, 'Rejected'),
    )

    description = models.CharField(verbose_name=_("Description"),
        null=False, blank=False, max_length=500,)
    scheduled_for = models.DateTimeField(verbose_name=_("Schedule for"),)
    main_script = models.TextField(verbose_name=_("Main Script"),
        null=False, blank=False)
    rollback_script = models.TextField(verbose_name=_("Rollback Script"),
        null=True, blank=True)
    host_query = models.TextField(verbose_name=_("Query Hosts"),
        null=False, blank=False)
    maximum_workers = models.PositiveSmallIntegerField(verbose_name=_("Maximum workers"),
        null=False, default=1)
    celery_task_id = models.CharField(verbose_name=_("Celery task Id"),
        null=True, blank=True, max_length=50,)
    status = models.IntegerField(choices=MAINTENANCE_STATUS, default=WAITING)

    def __unicode__(self):
       return "%s" % self.description

    def save_host_maintenance(self,):
        hosts = Host.objects.raw(self.host_query)
        try:
            for host in hosts:
                hm = HostMaintenance()
                hm.host = host
                hm.maintenance = self
                hm.save()
        except Exception, e:
            LOG.warn("There is something wrong with the executed query")
            LOG.warn("Error: {}".format(e.args[1]))
            self.status = self.REJECTED
            self.save()
            return False

        return True


class HostMaintenance(BaseModel):
    ERROR = 0
    SUCCESS = 1
    RUNNING = 2
    ROLLBACK = 3
    WAITING = 4
    ROLLBACK_ERROR = 5
    ROLLBACK_SUCCESS = 6

    MAINTENANCE_STATUS = (
        (ERROR, 'Error'),
        (SUCCESS, 'Success'),
        (RUNNING, 'Running'),
        (ROLLBACK, 'Rollback'),
        (WAITING, 'Waiting'),
        (ROLLBACK_ERROR, 'Rollback error'),
        (ROLLBACK_SUCCESS, 'Rollback success'),
    )

    started_at = models.DateTimeField(verbose_name=_("Started at"), null=True)
    finished_at = models.DateTimeField(verbose_name=_("Finished at"),null=True)
    main_log = models.TextField(verbose_name=_("Main Script"),
        null=True, blank=True)
    rollback_log = models.TextField(verbose_name=_("Rollback Script"),
        null=True, blank=True)
    status = models.IntegerField(choices=MAINTENANCE_STATUS, default=WAITING)
    host = models.ForeignKey(Host, related_name="host_maintenance",)
    maintenance = models.ForeignKey(Maintenance, related_name="maintenance",)

    class Meta:
        unique_together = (("host", "maintenance"),)
        index_together = [["host", "maintenance"],]

    def __unicode__(self):
        return "%s %s" % (self.host, self.maintenance)

simple_audit.register(Maintenance)
simple_audit.register(HostMaintenance)



#########
# SIGNALS#
#########

@receiver(pre_delete, sender=Maintenance)
def database_pre_delete(sender, **kwargs):
    """
    maintenance pre delete signal. Revoke scheduled task and remove
    its HostMaintenance objects
    """
    maintenance = kwargs.get("instance")
    LOG.debug("maintenance pre-delete triggered")
    HostMaintenance.objects.filter().delete()
    revoke(task_id=maintenance.celery_task_id)



@receiver(post_save, sender=Maintenance)
def maintenance_post_save(sender, **kwargs):
    """
     maintenance post save signal. Creates the maintenance
     task on celery and its HostMaintenance objetcs.
    """
    maintenance = kwargs.get("instance")
    is_new = kwargs.get("created")
    LOG.debug("maintenance post-save triggered")

    if is_new or not maintenance.celery_task_id:
        LOG.info("Spawning task and HostMaintenance objects...")

        if maintenance.save_host_maintenance():
            task = execute_scheduled_maintenance.apply_async(args=[maintenance],
                eta=maintenance.scheduled_for)

            maintenance.celery_task_id = task.task_id
            maintenance.save()

@@ -413,24 +413,16 @@
 task
-.control
  import 
 revo
@@ -417,22 +417,23 @@
  import 
-revoke
+control
 %0Afrom .t
@@ -2119,65 +2119,901 @@
     
-self.save()%0A            return False%0A%0A        return True
+post_save.disconnect(maintenance_post_save, sender=Maintenance)%0A            self.save()%0A            post_save.connect(maintenance_post_save, sender=Maintenance)%0A            return False%0A%0A        return True%0A%0A    def is_waiting_to_run(self):%0A        if self.status == self.FINISHED:%0A            LOG.info(%22Maintenance has already run!%22)%0A            return False%0A%0A        inspect = control.inspect()%0A        scheduled_tasks = inspect.scheduled()%0A        hosts = scheduled_tasks.keys()%0A%0A        for host in hosts:%0A            try:%0A                scheduled_tasks = scheduled_tasks%5Bhost%5D%0A            except TypeError:%0A                LOG.warn(%22There are not scheduled tasks%22)%0A                LOG.info(scheduled_tasks)%0A                return False%0A%0A            for task in scheduled_tasks:%0A                if  task%5B'id'%5D == self.celery_task_id:%0A                    return True%0A%0A        return False%0A
 %0A%0A%0Ac
@@ -4684,16 +4684,24 @@
 e()%0A    
+control.
 revoke(t

Add 'is_waiting_to_run' on Maintenance. The Maintenance should be rejected if the 'host_query' has an error. Change celery import to avoid cyclic imports