import grok
import logging
import os
try:
    from zope.authentication.interfaces import IAuthentication
except:
    # BBB
    from zope.app.security.interfaces import IAuthentication
from zope.component import createObject, getUtilitiesFor
try:
    from zope.pluggableauth import PluggableAuthentication
except ImportError:
    # BBB
    from zope.app.authentication.authentication import PluggableAuthentication

from waeup.sirp.authentication import setup_authentication
from waeup.sirp.datacenter import DataCenter
from waeup.sirp.interfaces import (
    IUniversity, IDataCenter, IWAeUPSIRPPluggable,
    IDataCenterStorageMovedEvent)
from waeup.sirp.users import UserContainer

class University(grok.Application, grok.Container):
    """A university.
    """
    grok.implements(IUniversity)
    # Setup authentication for this app. Note: this is only
    # initialized, when a new instance of this app is created.
    grok.local_utility(
        PluggableAuthentication, provides = IAuthentication,
        setup = setup_authentication,)
    
    @property
    def logger(self):
        sitename = self.__name__
        loggername = 'waeup.sirp.%s' % sitename
        logger = logging.getLogger(loggername)
        if not logger.handlers:
            logger = self._setupLogger(logger)
        return logger
        
    
    def __init__(self, name=u'Sample University', **kw):
        super(University, self).__init__(**kw)
        self.name = name
        self.setup()

    def setup(self):
        self['users'] = UserContainer()
        self['datacenter'] = DataCenter()

        self['students'] = createObject(u'waeup.StudentContainer')
        self['hostels'] = createObject(u'waeup.HostelContainer')
        self._createPlugins()

    def _createPlugins(self):
        """Create instances of all plugins defined somewhere.
        """
        for name, plugin in getUtilitiesFor(IWAeUPSIRPPluggable):
            plugin.setup(self, name, self.logger)
        return
        
    def _setupLogger(self, logger):
        """Setup general application logger.

        The logfile will be stored in the datacenter logs/ dir.
        """
        logdir = os.path.join(self['datacenter'].storage, 'logs')
        if not os.path.exists(logdir):
            os.mkdir(logdir)
        filename = os.path.join(logdir, 'application.log')

        # Create a rotating file handler logger for application.
        handler = logging.handlers.RotatingFileHandler(
            filename, maxBytes=5*1024**1, backupCount=7)
        formatter = logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        
        # Don't send log msgs to ancestors. This stops displaying
        # logmessages on the commandline.
        logger.propagate = False
        logger.addHandler(handler)
        return logger

@grok.subscribe(IDataCenter, IDataCenterStorageMovedEvent)
def handle_storage_move(obj, event):
    """Event handler, in case datacenter storage moves.

    We initialize the application log again, then.
    """
    app = grok.getSite()
    if app is None:
        return
    if obj is not app['datacenter']:
        return
    logger = app.logger
    logger.warn('Log Dir moved. Closing.')
    handlers = logger.handlers
    for handler in handlers:
        logger.removeHandler(handler)
    app._setupLogger(logger)
    logger.warn('Log file moved. Opening.')
