# -*- coding: utf-8 -*-
from Acquisition import aq_base
from plone.app.layout.nextprevious.interfaces import INextPreviousProvider
from plone.memoize.instance import memoize
from plone.registry.interfaces import IRegistry
from Products.ATContentTypes.interfaces.folder import IATFolder
from Products.CMFCore.utils import getToolByName
from zope.component import adapts
from zope.component import getUtility
from zope.interface import implements


class ATFolderNextPrevious(object):
    """Let a folder act as a next/previous provider. This will be
    automatically found by the @@plone_nextprevious_view and viewlet.
    """

    implements(INextPreviousProvider)
    adapts(IATFolder)

    def __init__(self, context):
        self.context = context
        registry = getUtility(IRegistry)
        self.view_action_types = registry.get(
            'plone.types_use_view_action_in_listings', [])

    def getNextItem(self, obj):
        relatives = self.itemRelatives(obj.getId())
        return relatives["next"]

    def getPreviousItem(self, obj):
        relatives = self.itemRelatives(obj.getId())
        return relatives["previous"]

    @property
    def enabled(self):
        return self.context.getNextPreviousEnabled()

    @memoize
    def itemRelatives(self, oid):
        """Get the relative next and previous items
        """
        folder = self.context
        catalog = getToolByName(self.context, 'portal_catalog')
        position = folder.getObjectPosition(oid)

        previous = None
        next = None

        # Get the previous item
        if position - 1 >= 0:
            prev_brain = catalog(self.buildNextPreviousQuery(
                position=position - 1, range='max', sort_order='reverse'))
            if prev_brain and len(prev_brain) > 0:
                previous = self.buildNextPreviousItem(prev_brain[0])

        # Get the next item
        counter = getattr(aq_base(folder), 'objectCount', None)
        if counter is not None:
            count = counter()
        else:
            count = len(folder)

        if (position + 1) < count:
            next_brain = catalog(self.buildNextPreviousQuery(
                position=position + 1, range='min'))

            if next_brain and len(next_brain) > 0:
                next = self.buildNextPreviousItem(next_brain[0])

        nextPrevious = {
            'next': next,
            'previous': previous,
        }

        return nextPrevious

    def buildNextPreviousQuery(self, position, range, sort_order=None):
        sort_on = 'getObjPositionInParent'

        query = {}
        query['sort_on'] = sort_on
        query['sort_limit'] = 1
        query['path'] = dict(query='/'.join(self.context.getPhysicalPath()),
                             depth=1)

        # Query the position using a range
        if position == 0:
            query[sort_on] = 0
        else:
            query[sort_on] = dict(query=position, range=range)

        # Filters on content
        query['is_default_page'] = False
        query['is_folderish'] = False

        # Should I sort in any special way ?
        if sort_order:
            query['sort_order'] = sort_order

        return query

    def buildNextPreviousItem(self, brain):
        return {'id': brain.getId,
                'url': self.getViewUrl(brain),
                'title': brain.Title,
                'description': brain.Description,
                'portal_type': brain.portal_type,
                }

    def getViewUrl(self, brain):
        """create link and support contents that requires /view
        """
        item_url = brain.getURL()

        if brain.portal_type in self.view_action_types:
            item_url += '/view'

        return item_url
