from plone import api
from plone.dexterity.interfaces import IDexterityFTI
from ploneintranet.network.interfaces import INetworkTool
from zope.interface.interfaces import ComponentLookupError

import logging

log = logging.getLogger(__name__)


def setupVarious(context):
    log.info("setupVarious")

    # Replace ALL IDublinCore behaviors with our own variant.
    # Doing it like this instead of via profiles/default/types/*.xml
    # - so we don't have to list all types (and will miss some in error)
    # - and we don't have to list all behaviors (and will purge some in error)
    # This can still be overridden per-type in your policy suite types/*xml
    # But there should be no need, this is fully backward compatible
    # and can be cleanly uninstalled
    replace_all_behaviors()


def uninstall(context):
    log.info("uninstall")
    restore_all_behaviors()

    portal = api.portal.get()
    _remove_persistent_utility(portal)
    # _remove_tool(portal)


REPLACEMENT_BEHAVIORS = [
    {"old": "plone.dublincore", "new": "quaive.dublincore"},
    {"old": "plone.categorization", "new": "quaive.categorization"},
]


def replace_all_behaviors():
    types_tool = api.portal.get_tool("portal_types")
    for fti_id in types_tool.listTypeTitles().keys():
        fti = types_tool.get(fti_id)
        if IDexterityFTI.providedBy(fti):
            for r_beh in REPLACEMENT_BEHAVIORS:
                replace_behavior(fti, r_beh["old"], r_beh["new"], "replace")


def restore_all_behaviors():
    types_tool = api.portal.get_tool("portal_types")
    for fti_id in types_tool.listTypeTitles().keys():
        fti = types_tool.get(fti_id)
        if IDexterityFTI.providedBy(fti):
            for r_beh in REPLACEMENT_BEHAVIORS:
                replace_behavior(fti, r_beh["new"], r_beh["old"], "restore")


def replace_behavior(fti, old, new, msg):
    behaviors = []
    for beh in fti.behaviors:
        if beh == old:
            log.info("%s %s behavior on %s", msg, beh, fti)
            beh = new
        behaviors.append(beh)
    fti.behaviors = behaviors


def _remove_persistent_utility(portal):
    sm = portal.getSiteManager()
    sm.unregisterUtility(provided=INetworkTool)
    try:
        util = sm.getUtility(INetworkTool)
        del util
    except ComponentLookupError:
        pass
    sm.utilities.unsubscribe((), INetworkTool)
    try:
        del sm.utilities.__dict__["_provided"][INetworkTool]
    except KeyError:
        pass
    log.info("Removed INetworkTool utility")
