# coding=utf-8
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from common import const
from syscfg.models import Role
from organ.models import Position,OrgUnit


class Modal(models.Model):
    """

    """
    import datetime
    index_weight = 1
    code = models.CharField(_("workflow code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
    name = models.CharField(_("workflow name"),max_length=const.DB_CHAR_NAME_40)
    description = models.TextField(_("description"),blank=True,null=True)
    content_type = models.ForeignKey(ContentType,verbose_name=_("content type"),limit_choices_to={"app_label__in":['basedata','organ']})
    app_name = models.CharField(_("app name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
    model_name = models.CharField(_("model name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
    # added by zhugl 2015-05-10
    begin = models.DateField(_("begin date"),blank=True,null=True,default=datetime.date.today)
    end = models.DateField(_("end date"),blank=True,null=True,default=datetime.date(9999,12,31))

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

    class Meta:
        verbose_name = _("workflow model")
        verbose_name_plural = _("workflow model")


class Node(models.Model):
    """
    submitter()
    upper()
    user()
    role()
    position()
    sql()
    etc:upper('zhangsan','lisi')
    """
    HANDLER_TYPE = (
        (1, _("designated user")),
        (2, _("designated position")),
        (3, _("designated role")),
        (4, _("submitter")),
    )
    index_weight = 2
    modal = models.ForeignKey(Modal,verbose_name=_("workflow model"))
    code = models.CharField(_("node code"),max_length=const.DB_CHAR_CODE_4,blank=True,null=True)
    name = models.CharField(_("node name"),max_length=const.DB_CHAR_NAME_80)
    tooltip = models.CharField(_('tooltip words'),blank=True,null=True,max_length=const.DB_CHAR_NAME_120)

    start = models.BooleanField(_("start node"),default=False)
    stop = models.BooleanField(_("stop node"),default=False)
    can_terminate = models.BooleanField(_("can terminate"),default=False)
    can_deny = models.BooleanField(_("can deny"),default=True)
    can_edit = models.BooleanField(_("can edit"),default=False)

    email_notice = models.BooleanField(_("email notice"),default=True)
    short_message_notice = models.BooleanField(_("short message notice"),default=False)
    approve_node = models.BooleanField(_("approve node"),default=False)
    handler = models.TextField(_("handler"),blank=True,null=True,help_text=u'自定义SQL语句，优先高于指定用户、岗位、角色')
    # added by zhugl 2015-05-10
    handler_type = models.IntegerField(_("handler type"),choices=HANDLER_TYPE,default=1)
    positions = models.ManyToManyField(Position,verbose_name=_("designated position"),blank=True)
    roles = models.ManyToManyField(Role,verbose_name=_("designated role"),blank=True)
    users = models.ManyToManyField(User,verbose_name=_("designated user"),blank=True)
    departments = models.ManyToManyField(OrgUnit,verbose_name=_("designated department"),blank=True)
    next = models.ManyToManyField('self',blank=True,verbose_name=_("next node"),symmetrical=False)
    # added by zhugl 2015-06-30
    next_user_handler = models.CharField(_('next user handler'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
    next_node_handler = models.CharField(_('next node handler'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
    status_field = models.CharField(_('status field'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
    status_value = models.CharField(_('status value'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
    action = models.CharField(_('execute action'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if not self.code:
            fmt = 'N%02d'
            self.code = fmt % (self.modal.node_set.count()+1)
        super(Node,self).save(force_insert,force_update,using,update_fields)

    def __unicode__(self):
        return "%s-%s" % (self.code, self.name)

    class Meta:
        verbose_name = _("workflow node")
        verbose_name_plural = _("workflow node")


class Instance(models.Model):
    """

    """
    STATUS = (
        (1, _("NEW")),
        (2, _("IN PROGRESS")),
        (3, _("DENY")),
        (4, _("TERMINATED")),
        (9, _("APPROVED")),
        (99, _("COMPLETED"))
    )
    index_weight = 3
    code = models.CharField(_("code"),blank=True,null=True,max_length=const.DB_CHAR_CODE_10)
    modal = models.ForeignKey(Modal,verbose_name=_("workflow model"))
    object_id = models.PositiveIntegerField("object id")
    starter = models.ForeignKey(User,verbose_name=_("start user"),related_name="starter")
    start_time = models.DateTimeField(_("start time"),auto_now_add=True)
    approved_time = models.DateTimeField(_("approved time"),blank=True,null=True)
    status = models.IntegerField(_("status"),default=1,choices=STATUS)
    current_nodes = models.ManyToManyField(Node,verbose_name=_("current node"),blank=True)

    def __unicode__(self):
        return '%s' % self.code

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        super(Instance,self).save(force_insert,force_update,using,update_fields)
        if not self.code:
            self.code = 'S%05d'%self.id
            self.save()

    class Meta:
        verbose_name = _("workflow instance")
        verbose_name_plural = _("workflow instance")


class History(models.Model):
    """
    workflow history
    """
    PROCESS_TYPE = (
        (0, _("SUBMIT")),
        (1, _("AGREE")),
        (3, _("DENY")),
        (4, _("TERMINATE")),
    )
    index_weight = 5
    inst = models.ForeignKey(Instance,verbose_name=_("workflow instance"))
    node = models.ForeignKey(Node,verbose_name=_("workflow node"),blank=True,null=True)
    user = models.ForeignKey(User,verbose_name=_("submitter"))
    pro_time = models.DateTimeField(_("process time"),auto_now_add=True)
    pro_type = models.IntegerField(_("process type"),choices=PROCESS_TYPE,default=0)
    memo = models.CharField(_("memo"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)

    def get_node_desc(self):
        if self.node:
            return self.node.name
        else:
            return u'启动'

    def get_action_desc(self):
        action_mapping = {0:u'提交',1:u'同意',3:u'拒绝',4:u'终止',}
        # print action_mapping
        if self.pro_type:
            return action_mapping[self.pro_type]
        else:
            return u'提交'

    def get_memo_desc(self):
        if self.memo:
            return self.memo
        else:
            return ''

    class Meta:
        verbose_name = _("workflow history")
        verbose_name_plural = _("workflow history")
        ordering = ['inst','pro_time']


class TodoList(models.Model):
    """

    """
    index_weight = 4
    code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_10,blank=True,null=True)
    inst = models.ForeignKey(Instance,verbose_name=_("workflow instance"))
    node = models.ForeignKey(Node,verbose_name=_("current node"),blank=True,null=True)
    app_name = models.CharField(_("app name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
    model_name = models.CharField(_("model name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
    user = models.ForeignKey(User,verbose_name=_("handler"))
    arrived_time = models.DateTimeField(_("arrived time"),auto_now_add=True)
    is_read = models.BooleanField(_("is read"),default=False)
    read_time = models.DateTimeField(_("read time"),blank=True,null=True)
    status = models.BooleanField(_("is done"),default=False)

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        super(TodoList,self).save(force_update,force_update,using,update_fields)
        if not self.code:
            self.code = 'TD%05d' % self.id
            self.save()

    def node_dsc(self):
        if self.node:
            return u'%s'%self.node.name
        else:
            return u'启动'

    def code_link(self):
        return format_html("<a href='/admin/{}/{}/{}'>{}</a>",
                           self.app_name,self.model_name,self.inst.object_id,self.code)
    code_link.allow_tags = True
    code_link.short_description = _("code")

    def href(self):
        import sys
        # reload(sys)
        sys.setdefaultencoding("utf-8")
        ct = ContentType.objects.get(app_label=self.app_name,model=self.model_name)
        obj = ct.get_object_for_this_type(id=self.inst.object_id)
        title = u"%s" % (obj)
        return format_html("<a href='/admin/{}/{}/{}'>{}</a>",
                           self.app_name,self.model_name,self.inst.object_id,title)
    def modal_dsc(self):
        return u'%s'%(self.inst.modal.name)
    modal_dsc.short_description = u'业务流程'

    def start_time(self):
        return self.inst.start_time.strftime('%Y-%m-%d %H:%M')

    href.allow_tags = True
    href.short_description = _("description")
    node_dsc.short_description = _('current node')

    def submitter(self):
        if self.inst.starter.last_name or self.inst.starter.first_name:
            return u"%s%s"%(self.inst.starter.last_name,self.inst.starter.first_name)
        return u"%s"%(self.inst.starter.username)
    submitter.short_description = _("submitter")

    class Meta:
        verbose_name = _("workflow todo")
        verbose_name_plural = _("workflow todo")
        ordering = ['user','-arrived_time']


def get_modal(app_label,model_name):
    """

    :param app_label:
    :param model_name:
    :return:
    """
    try:
        return Modal.objects.get(app_name=app_label,model_name=model_name)
    except Exception as e:
        return None


def get_instance(obj):
    """

    :param obj:
    :return:
    """
    if obj and obj._meta:
        modal = get_modal(obj._meta.app_label,obj._meta.model_name)
        if modal:
            try:
                return Instance.objects.get(modal=modal,object_id=obj.id)
            except Exception as e:
                return None
    else:
        return None
