# -*- coding: UTF-8 -*-
from five import grok
from zope import schema
from plone.namedfile import field as namedfile
from z3c.relationfield.schema import RelationChoice, RelationList
from plone.formwidget.contenttree import ObjPathSourceBinder

from plone.directives import form, dexterity
from plone.app.textfield import RichText
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
from zope.lifecycleevent.interfaces import IObjectModifiedEvent
from zope.schema.fieldproperty import FieldProperty
from AccessControl.interfaces import IRoleManager

from plone.app.discussion.browser.comments import CommentsViewlet 

# for debug purpose => log(...)
from Products.CMFPlone.utils import log

from ageliaco.tracker import _

import datetime

from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary
from zope.lifecycleevent.interfaces import IObjectCreatedEvent
from zope.app.container.interfaces import IObjectAddedEvent
from Products.CMFCore.utils import getToolByName

from plone.formwidget.autocomplete import AutocompleteMultiFieldWidget
from zope.interface import invariant, Invalid

from Acquisition import aq_inner, aq_parent
from zope.component import getUtility
from Products.CMFCore.interfaces import ISiteRoot

from DateTime import DateTime
from plone.indexer import indexer


class TwiceSameSupevisor(Invalid):
    __doc__ = _(u"Choisir un autre superviseur secondaire ou primaire!")


class GroupMembers(object):
    """Context source binder to provide a vocabulary of users in a given
    group.
    """
    
    grok.implements(IContextSourceBinder)
    
    def __init__(self, group_name):
        self.group_name = group_name
    
    def __call__(self, context):
        acl_users = getToolByName(context, 'acl_users')
        group = acl_users.getGroupById(self.group_name)
        terms = []
        terms.append(SimpleVocabulary.createTerm('', str(''), ''))
        if group is not None:
            for member_id in group.getMemberIds():
                user = acl_users.getUserById(member_id)
                if user is not None:
                    member_name = user.getProperty('fullname') or member_id
                    terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name))
            
        return SimpleVocabulary(terms)    

class getUserWithRole(object):
    """Context source binder to provide a vocabulary of users in a given
    group.
    """
    
    grok.implements(IContextSourceBinder)
    
    def __init__(self, role_name):
        self.role_name = role_name
    
    def __call__(self, context):
        acl_users = getToolByName(context, 'acl_users')
        parent = context.aq_inner.aq_parent
        log("context : " + context.__name__ + " parent : " + parent.__name__)
        users_roles = context.get_local_roles()
        users_with_the_role = [x[0] for x in users_roles if self.role_name in x[1]]
        
        terms = []
        terms.append(SimpleVocabulary.createTerm('', str(''), ''))
        if users_with_the_role is not None:
            for member_id in users_with_the_role:
                log( member_id)
                user = acl_users.getUserById(member_id)
                if user is not None:
                    member_name = user.getProperty('fullname') or member_id
                    terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name))
            
        return SimpleVocabulary(terms)    



        

class IIssue(form.Schema):
    """
    Issue
    """
    
    # -*- Your Zope schema definitions here ... -*-
    responsible = schema.Choice(
            title=_(u"Responsable"),
            description=_(u"Personne qui supervise cette tâche"),
            source=getUserWithRole('Reviewer'),
            required=False,
        )


    content = RichText(
            title=_(u"Présentation"),
            description=_(u"Description de la tâche"),
            required=True,
        )    

    deadline = schema.Datetime(
            title=_(u"Deadline"),
            required=False,
        )



class AddForm(dexterity.AddForm):
    grok.name('issue')        

@form.default_value(field=IIssue['deadline'])
def startDefaultValue(data):
    # To get hold of the folder, do: context = data.context
    year = datetime.timedelta(days=365)
    return datetime.datetime.today() + year


@grok.subscribe(IIssue, IObjectAddedEvent)
def setReviewer(issue, event):
    log( "=== Default Reviewer Role Attribution in Issue ===")
    acl_users = getToolByName(issue, 'acl_users')
    mail_host = getToolByName(issue, 'MailHost')
    portal_url = getToolByName(issue, 'portal_url')
    
    parent = issue.aq_inner.aq_parent
    log( parent.__name__ + "parent local roles : " +str(parent.get_local_roles())
            + "\naq_parent'parent local roles : " + str(parent.aq_parent.get_local_roles()))
    
    users_with_the_role = []
    if parent.Type() == "Tracker":
        log( "Testing parent's reviewers")
        users_roles = parent.get_local_roles()
        log("users roles : " + str( users_roles))
        users_with_the_role = [x[0] for x in users_roles if 'Reviewer' in x[1]]
        for member in users_with_the_role:
            log("member : " + member)

    #Add local roles to a group
    if IRoleManager.providedBy(issue):
        for member in users_with_the_role:
            log( "adding roles (Reviewer) to " + member )
            issue.manage_addLocalRoles(member, ['Reviewer'])

    return


@indexer(IIssue)
def deadlineIndexer(obj):
    if obj.end is None:
        return None
    return DateTime(obj.deadline.isoformat())
grok.global_adapter(deadlineIndexer, name="deadline")


####
# the idea is to provide a way to manage expiring dates to workflow states
# so an issue could have start and end dates to its "opened" state
# and when it expires a transition (close) is trigered and eventually its script also
#
# from http://lists.plone.org/pipermail/plone-setup/2006-February/006386.html
####
# from DateTime import DateTime
# import time
# 
# def applyTransition(self, transition, time_offset):
#      pc = self.portal_catalog
#      pw = self.portal_workflow
# 
#      t0 = DateTime(time.time() - time_offset * 3600)
# 
#      pending = 0
#      promoted = 0
# 
#      #
#      # Grab all of the offers that are only visible to premium members
#      #
# 
#      for obrain in pc.queryCatalog({'portal_type':"OfferFolder", 'review_state':"respondable_premium"}):
#          o = obrain.getObject()
#          last_transition = o.workflow_history['offer_folder_workflow'][-1]
#          t1 = last_transition.get('time')
# 
#          pending += 1
#          #
#          # Check to see if this offer has passed the blackout period
#          #
#          pending_objs = {}
#          if t1 < t0:
#              promoted += 1
#              #
#              # TODO: currently it silently ignores objects who's transition does not exist
#              #
#              for t in pw.getTransitionsFor(o):
#                  if t['id'] == transition:
#                     pw.doActionFor(o, transition)
# 
#          pending_objs[pending] = o.absolute_url()

# start and end date suppressed, because this role could be played by history
# 
#     start = schema.Datetime(
#             title=_(u"Start date"),
#             required=False,
#         )
# 
#     end = schema.Datetime(
#             title=_(u"End date"),
#             required=False,
#         )
        


# @form.default_value(field=IIssue['start'])
# def startDefaultValue(data):
#     # To get hold of the folder, do: context = data.context
#     return datetime.datetime.today() 
# 
# 
# @form.default_value(field=IIssue['end'])
# def endDefaultValue(data):
#     # To get hold of the folder, do: context = data.context
#     return datetime.datetime.today() + datetime.timedelta(10)
    
