from DateTime import DateTime
from plone.app.content.browser.contents import ContentsBaseAction
from plone.app.content.interfaces import IStructureAction
from plone.app.dexterity.behaviors.metadata import ICategorization
from plone.app.widgets.utils import get_datetime_options
from plone.dexterity.interfaces import IDexterityContent
from Products.CMFCore.interfaces._content import IFolderish
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.component import getUtility
from zope.component.hooks import getSite
from zope.i18n import translate
from zope.interface import implementer
from zope.schema.interfaces import IVocabularyFactory

import json


@implementer(IStructureAction)
class PropertiesAction:

    template = ViewPageTemplateFile('templates/properties.pt')
    order = 8

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def get_options(self):
        base_vocabulary = '%s/@@getVocabulary?name=' % getSite().absolute_url()
        return {
            'tooltip': translate(_('Properties'), context=self.request),
            'id': 'properties',
            'icon': 'edit',
            'url': self.context.absolute_url() + '/@@fc-properties',
            'form': {
                'title': translate(_('Modify properties on items'), context=self.request),
                'template': self.template(
                    vocabulary_url='%splone.app.vocabularies.Users' % (
                        base_vocabulary),
                    pattern_options=json.dumps(get_datetime_options(self.request))
                ),
                'dataUrl': self.context.absolute_url() + '/@@fc-properties',
            }
        }

class PropertiesActionView(ContentsBaseAction):
    success_msg = _('Successfully updated metadata')
    failure_msg = _('Failure updating metadata')
    required_obj_permission = 'Modify portal content'

    def __call__(self):

        if self.request.form.get('render') == 'yes':
            lang_factory = getUtility(
                IVocabularyFactory,
                'plone.app.vocabularies.SupportedContentLanguages'
            )
            lang_vocabulary = lang_factory(self.context)
            languages = [
                {
                    'title': term.title,
                    'value': term.value
                }
                for term in lang_vocabulary
            ]
            return self.json({
                'languages': [{
                    'title': translate(
                        _('label_no_change', default='No change'),
                        context=self.request,
                    ),
                    'value': ''
                }] + languages
            })

        self.putils = getToolByName(self.context, 'plone_utils')
        self.effectiveDate = self.request.form.get('effectiveDate')
        self.expirationDate = self.request.form.get('expirationDate')
        self.copyright = self.request.form.get('copyright')
        self.contributors = self.request.form.get('contributors')
        if self.contributors:
            self.contributors = self.contributors.split(',')
        else:
            self.contributors = []
        self.creators = self.request.form.get('creators', '')
        if self.creators:
            self.creators = self.creators.split(',')
        self.exclude = self.request.form.get('exclude-from-nav')
        self.language = self.request.form.get('language')
        self.recurse = self.request.form.get('recurse', 'no') == 'yes'
        return super().__call__()

    def dx_action(self, obj):
        if self.effectiveDate and hasattr(obj, 'effective_date'):
            obj.effective_date = DateTime(self.effectiveDate)
        if self.expirationDate and hasattr(obj, 'expiration_date'):
            obj.expiration_date = DateTime(self.expirationDate)
        if self.copyright and hasattr(obj, 'rights'):
            obj.rights = self.copyright
        if self.contributors and hasattr(obj, 'contributors'):
            obj.contributors = tuple(self.contributors)
        if self.creators and hasattr(obj, 'creators'):
            obj.creators = tuple(self.creators)
        if self.exclude and hasattr(obj, 'exclude_from_nav'):
            obj.exclude_from_nav = self.exclude == 'yes'

        behavior_categorization = ICategorization(obj)
        if self.language and behavior_categorization:
            behavior_categorization.language = self.language

    def at_action(self, obj):
        if self.effectiveDate:
            try:
                obj.setEffectiveDate(DateTime(self.effectiveDate))
            except AttributeError:
                pass
        if self.expirationDate:
            try:
                obj.setExpirationDate(DateTime(self.expirationDate))
            except AttributeError:
                pass
        if self.copyright:
            try:
                obj.setRights(self.copyright)
            except AttributeError:
                pass
        if self.contributors:
            try:
                obj.setContributors(self.contributors)
            except AttributeError:
                pass
        if self.creators:
            try:
                obj.setCreators(self.creators)
            except AttributeError:
                pass
        if self.exclude:
            try:
                obj.setExcludeFromNav(self.exclude == 'yes')
            except AttributeError:
                pass
        if self.language:
            try:
                obj.setLanguage(self.language)
            except AttributeError:
                pass

    def action(self, obj, bypass_recurse=False):

        if self.putils.isDefaultPage(obj):
            self.action(obj.aq_parent, bypass_recurse=True)
        recurse = self.recurse and not bypass_recurse
        if recurse and IFolderish.providedBy(obj):
            for sub in obj.values():
                self.action(sub)

        if IDexterityContent.providedBy(obj):
            self.dx_action(obj)
        else:
            self.at_action(obj)

        obj.reindexObject()
