"""Declaration support for Zope Interfaces"""

__all__ = []

from types import ClassType

from adapters import *
from api import declareImplementation, advise, adapt
from interfaces import IOpenProtocol, Protocol
from advice import metamethod, supermeta


# Monkeypatch Zope Interfaces

try:
    import zope.interface as zi

except ImportError:
    ZopeInterfaceTypes = []
    zi = None

else:

    def __adapt__(self, obj):
        return adapt(self,IOpenProtocol).__adapt__(obj)

    try:
        from zope.interface import adapter_hooks
    except ImportError:
        try:
            from zope.interface.interface import adapter_hooks
        except ImportError:
            zi.Interface.__class__.__adapt__ = __adapt__
            adapter_hooks = []

    adapter_hooks.append(__adapt__)
    ZopeInterfaceTypes = [zi.Interface.__class__]

    del __adapt__, adapter_hooks


# Adapter for Zope X3 Interfaces

class ZopeInterfaceAsProtocol(StickyAdapter, Protocol):
    advise(
        instancesProvide=[IOpenProtocol],
        asAdapterForTypes=ZopeInterfaceTypes,
    )
    attachForProtocols = IOpenProtocol,

    def __init__(self, ob):
        StickyAdapter.__init__(self,ob)
        Protocol.__init__(self)

    if ZopeInterfaceTypes and hasattr(ZopeInterfaceTypes[0],'providedBy'):
        def __adapt__(self, obj):
            if self.subject.providedBy(obj):
                return obj
            return supermeta(ZopeInterfaceAsProtocol,self).__adapt__(obj)
    else:
        def __adapt__(self, obj):
            if self.subject.isImplementedBy(obj):
                return obj
            return supermeta(ZopeInterfaceAsProtocol,self).__adapt__(obj)

    def registerImplementation(self,klass,adapter=NO_ADAPTER_NEEDED,depth=1):

        if adapter is NO_ADAPTER_NEEDED:
            zi.classImplements(klass, self.subject)

        elif adapter is DOES_NOT_SUPPORT:
            ifaces = zi.Declaration(
                [i.__iro__ for i in zi.implementedBy(klass)]
            ) - self.subject
            zi.classImplementsOnly(klass, ifaces)

        return supermeta(ZopeInterfaceAsProtocol,self).registerImplementation(
            klass,adapter,depth
        )

    registerImplementation = metamethod(registerImplementation)

    def registerObject(self, ob, adapter=NO_ADAPTER_NEEDED, depth=1):

        if adapter is NO_ADAPTER_NEEDED:
            zi.directlyProvides(ob,self.subject)

        elif adapter is DOES_NOT_SUPPORT:
            zi.directlyProvides(ob, zi.directlyProvidedBy(ob)-self.subject)

        return supermeta(ZopeInterfaceAsProtocol,self).registerObject(
            ob, adapter, depth
        )

    registerObject = metamethod(registerObject)


    def getImpliedProtocols(self):
        protos = super(ZopeInterfaceAsProtocol,self).getImpliedProtocols()
        return list(protos) + [
            (i,(NO_ADAPTER_NEEDED,1)) for i in self.subject.__bases__
                if i is not zi.Interface
        ]


    def __getstate__(self):
        state = self.__dict__.copy()
        del state['_Protocol__lock']        # locks can't be pickled
        del state['_Protocol__listeners']   # and neither can weakref dict
        return state

    def __hash__(self):
        return hash(self.subject)

    def __cmp__(self,other):
        return cmp(self.subject, other)







