# a unique handle URL for each document (the available version only)

from persistent import Persistent

from zope.interface import Interface, implements
from zope.publisher.interfaces import NotFound

from zope.app import zapi
from zope.app.container.contained import Contained

from documentlibrary.core import flow
from hurry.workflow.interfaces import IWorkflowVersions

class Root(Persistent, Contained):
    pass

class IUnavailableDocument(Interface):
    pass

class IUnavailableFile(Interface):
    pass

class UnavailableDocument(Contained):
    implements(IUnavailableDocument)
    
    def __init__(self, context, name, document_id):
        self.__name__ = name
        self.__parent__ = context
        self.document_id = document_id

class UnavailableFile(Contained):
    implements(IUnavailableFile)

    def __init__(self, context, name):
        self.__name__ = name
        self.__parent__ = context
    
class BaseTraverser(object):
    def __init__(self, context, request):
        self.context = context
        self.request = request

    def publishTraverse(self, request, name):
        view = zapi.queryMultiAdapter((self.context, request), name=name)
        if view is not None:
            return view
        raise NotFound(self.context, name, request)

    def browserDefault(self, request):
        view_name = zapi.getDefaultViewName(self.context, request)
        view_uri = "@@" + view_name
        return self.context, (view_uri,)
    
class DocumentTraverser(BaseTraverser):
        
    def publishTraverse(self, request, name):
        context = self.context
        try:
            id = int(name)
        except ValueError:
            id = None
        
        if id is not None:
            wf_versions = zapi.getUtility(IWorkflowVersions)

            if wf_versions.hasVersionId(id):
                versions = wf_versions.getVersions(flow.AVAILABLE, id)
                if not versions:
                    versions = wf_versions.getVersions(flow.ALERTED, id)
                    if not versions:
                        return UnavailableDocument(self.context, name, id)
                # return the first and only version
                for version in versions:
                    return version

        return super(DocumentTraverser, self).publishTraverse(request, name)

class UnavailableDownloadTraverser(BaseTraverser):
    def publishTraverse(self, request, name):
        # get a version with id, any version at all, as file urls are
        # stable
        wf_versions = zapi.getUtility(IWorkflowVersions)
        for possible_state in flow.getNonArchivedStates():
            versions = wf_versions.getVersions(possible_state,
                                               self.context.document_id)
            if versions:
                doc = iter(versions).next()
                break
        else:
            # cannot find any version at all, shouldn't really happen
            # but fall back anyway
            return super(UnavailableDownloadTraverser, self).publishTraverse(
                request, name)
        from zope.security.proxy import removeSecurityProxy
        # can look at document, no matter what role we have
        doc = removeSecurityProxy(doc)
        
        # now check whether we recognize filename
        if doc.file.filename == name:
            return UnavailableFile(self.context, name)
        elif doc.pdf is not None and doc.pdf.filename == name:
            return UnavailableFile(self.context, name)
        elif doc.plaintext is not None and doc.plaintext.filename == name:
            return UnavailableFile(self.context, name)
        return super(UnavailableDownloadTraverser, self).publishTraverse(
            request, name)
