"""Define a browser view for the FileExchange Container content type. In the FTI
configured in profiles/default/types/*.xml, this is being set as the default
view of that content type.
"""

import re
from zope.component import getUtility

from Acquisition import aq_inner, aq_parent
from AccessControl import Unauthorized

from zExceptions import BadRequest

from DateTime import DateTime

from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

from Products.CMFCore.utils import getToolByName

from OFS.ObjectManager import checkValidId

from plone.memoize.instance import memoize
from plone.i18n.normalizer.interfaces import IIDNormalizer

from Products.CMFPlone import PloneMessageFactory as _
from Products.FileExchange.config import ADD_PERMISSIONS, MODIFY_PERMISSION



class FileExchangeContainerView(BrowserView):
    """Default view of a fileexchange container
    """

    template = ViewPageTemplateFile('templates/fileexchangecontainer.pt')

    def __call__(self):
        context = aq_inner(self.context)
        self.errors = {}
        self.errors_edit = {}
        self.doDelete = self.doEdit = self.hasFiles = self.hasPerm =  False
        self.request.set('disable_border', True)
        self.putils = getToolByName(context, 'plone_utils')
        self.mtool = getToolByName(context, 'portal_membership')

        form = self.request.form

        if form.get('form.submitted', None) is not None:
            self.processForm()

        if self.request.get('delete'):
            self.prepareDelete()

        if self.request.get('edit'):
            self.prepareEdit()

        self.ownFiles = self.getFolderContentsByAuthor()
        self.receivedFiles = self.getFolderContentsNotByAuthor()
        self.hasFiles = self.ownFiles or self.receivedFiles
        self.fullname = self.mtool.getMemberInfo(self.getAuthor()).get('fullname', self.getAuthor())
        self.hasPerm = self.mtool.checkPermission(ADD_PERMISSIONS['FileExchange File'], context)

        return self.template()

    @memoize
    def getParent(self):
        return aq_parent(aq_inner(self.context))

    @memoize
    def getAuthor(self):
        return self.getParent().getId()

    def prepareContents(self, objects):
        context = aq_inner(self.context)
        contents = []

        for obj in objects:
            values = {'id'      : obj.getId(),
                      'title'   : obj.Title(),
                      'modified': obj.modified,
                      'icon'    : obj.getIcon(),
                      'url'     : '%s/%s' % (context.absolute_url(), obj.getId()),
                      'delUrl'  : '%s?delete=%s' % (context.absolute_url(), obj.getId()),
                      'editUrl' : '%s?edit=%s' % (context.absolute_url(), obj.getId()),
                      'hasPerm' : self.mtool.checkPermission(MODIFY_PERMISSION, obj),
                      }
            contents.append(values)
        return contents

    @memoize
    def getFolderContentsByAuthor(self):
        context = aq_inner(self.context)
        content = context.getFolderContents( contentFilter={'Creator' : self.getAuthor(),
                                                            'sort_on' : 'modified',
                                                            'sort_order' : 'reverse' }, full_objects=True )
        return self.prepareContents(content)

    @memoize
    def getFolderContentsNotByAuthor(self):
        context = aq_inner(self.context)
        found   = []
        content = context.getFolderContents( contentFilter={'sort_on' : 'modified',
                                                            'sort_order' : 'reverse' }, full_objects=True )
        for item in content:
            if not item.Creator() == self.getAuthor():
                found.append(item)
        return self.prepareContents(found)

    def getFileTitle(self, id):
        context = aq_inner(self.context)
        if context.get(id, None) is not None:
            return context.get(id, None).Title()
        return None

    def prepareEdit(self):
        context = aq_inner(self.context)
        file = context.get(self.request.get('edit'), None)
        if not self.mtool.checkPermission(MODIFY_PERMISSION, file):
            raise Unauthorized
        self.doEdit = self.request.get('edit')
        self.request.set('title_edit', self.getFileTitle(self.request.get('edit')))

    def prepareDelete(self):
        context = aq_inner(self.context)
        file = context.get(self.request.get('delete'), None)
        if not self.mtool.checkPermission(MODIFY_PERMISSION, file):
            raise Unauthorized
        self.doDelete = {'id'    : self.request.get('delete'),
                         'title' : self.getFileTitle(self.request.get('delete')),
                        }

    def validateForm(self):
        form = self.request.form
        errors = self.errors
        if form.get('id', None) is not None:
            errors = self.errors_edit

        # checks if the title are empty or has only whitespaces
        if re.match('^[\s]*$', form.get('title', '')) and re.match('^[\s]*$',form.get('title_edit', '')):
            errors['title'] = _(u'This field is required, please provide some information.')

        if form.get('file', '').filename == '' and form.get('id', None) is None:
            errors['file'] = _(u'This field is required, please provide some information.')
        return (len(errors) == 0)

    def processForm(self):
        context = aq_inner(self.context)
        form = self.request.form
        if form.get('form.button.Save', None) is not None:
            if self.validateForm():
                if form.get('id', None) is not None:
                    self.editFile(form.get('id', None))
                else:
                    self.addFile()
            else:
                if form.get('id', None) is not None:
                    self.request.set('edit', form.get('id', None))
                self.putils.addPortalMessage(_(u'Please correct the indicated errors.'))

        if form.get('form.button.Delete') and form.get('id'):
            self.deleteFile(form.get('id'))

        pass

    def deleteFile(self, id):
        context = aq_inner(self.context)
        try:
            file = context.get(id, None)
            if not self.mtool.checkPermission(MODIFY_PERMISSION, file):
                raise Unauthorized
            title = self.getFileTitle(id)
            context.manage_delObjects(id)
            message = _(u'${title} has been deleted.',
                        mapping={u'title' : title})
            self.putils.addPortalMessage(message)
        except:
            self.putils.addPortalMessage(_(u'Deleting file failed.'))

    def editFile(self, id):
        context = aq_inner(self.context)
        form = self.request.form
        try:
            file = context.get(id, None)
            if not self.mtool.checkPermission(MODIFY_PERMISSION, file):
                raise Unauthorized
            file.edit(title=form.get('title_edit'))
            if not form.get('file', '').filename == '':
                file.edit(file=form.get('file').read())
            file.reindexObject()
            self.putils.addPortalMessage(_(u'Changes saved.'))
        except:
            self.putils.addPortalMessage(_(u'Saving changes failed.'))

    def addFile(self):
        context = aq_inner(self.context)
        form = self.request.form
        try:
            typestool = getToolByName(context, 'portal_types')

            f = form.get('file')
            id = self._create_id(context, f.filename)

            typestool.constructContent(type_name='FileExchange File', container=context, id=id)
            file = context.get(id, None)
            file.manage_addLocalRoles(self.request.get('AUTHENTICATED_USER').getId(), ('FEFOwner',))
            file.edit(title=form.get('title'), file=f.read())
            file.reindexObject()
            self.putils.addPortalMessage(_(u'File successfully uploaded.'))
        except:
            self.putils.addPortalMessage(_(u'Fileupload failed.'))

    def _create_id(self, container, filename):
            id = startid = getUtility(IIDNormalizer).normalize(filename)
            ok = False
            counter = 0
            while not ok:
                try:
                    checkValidId(container, id)
                    ok = True
                except BadRequest:
                    counter += 1
                    ext = startid.rfind('.') > -1 and startid[startid.rfind('.'):] or ''
                    name = startid[:len(ext)*-1]
                    id = '%s-%s%s' % (name,counter,ext)
            return id







