import lovely.remotetask
import lovely.remotetask.interfaces
import lovely.remotetask.processor
import zeit.cms.content.interfaces
import zeit.cms.content.template
import zeit.cms.generation
import zeit.cms.relation.relation
import zeit.cms.repository.interfaces
import zeit.cms.repository.repository
import zeit.cms.workingcopy.workingcopy
import zope.component
import zope.component.interfaces
import zope.error.interfaces


def installLocalUtility(root, factory, name, interface, utility_name=u''):
    utility = factory()
    root[name] = utility
    site_manager = zope.component.getSiteManager()
    site_manager.registerUtility(utility, interface, name=utility_name)
    return root[name]


def installGeneralTaskService():
    site_manager = zope.component.getSiteManager()
    tasks = installLocalUtility(
        site_manager, lovely.remotetask.TaskService, 'tasks.general',
        lovely.remotetask.interfaces.ITaskService, utility_name='general')
    # Use MultiProcessor for parallel processing.
    tasks.processorFactory = lovely.remotetask.processor.MultiProcessor


def _install_serial_task_service(name, utility_name):
    site_manager = zope.component.getSiteManager()
    tasks = installLocalUtility(
        site_manager, lovely.remotetask.TaskService, name,
        lovely.remotetask.interfaces.ITaskService, utility_name=utility_name)
    # Use MultiProcessor with 1 Thread because it handles pulling from the
    # queue differently than the SingleProcessor.
    tasks.processorFactory = lovely.remotetask.processor.MultiProcessor
    tasks.processorArguments = {'maxThreads': 1}


def installEventTaskService():
    _install_serial_task_service('tasks.event', 'events')


def installLowPriorityTaskService():
    _install_serial_task_service('tasks.lowprio', 'lowprio')


def installRelations():
    site_manager = zope.component.getSiteManager()
    relations = installLocalUtility(
        site_manager,
        zeit.cms.relation.relation.Relations,
        'relations',
        zeit.cms.relation.interfaces.IRelations)
    relations.add_index(
        zeit.cms.relation.relation.referenced_by, multiple=True)


def installErrorReportingUtility(root):
    zope.app.appsetup.bootstrap.addConfigureUtility(
        root, zope.error.interfaces.IErrorReportingUtility, '',
        zeit.cms.browser.error.ErrorReportingUtility)


def install(root):
    installErrorReportingUtility(root)
    installLocalUtility(
        root, zeit.cms.repository.repository.repositoryFactory,
        'repository', zeit.cms.repository.interfaces.IRepository)
    installLocalUtility(
        root, zeit.cms.workingcopy.workingcopy.WorkingcopyLocation,
        'workingcopy', zeit.cms.workingcopy.interfaces.IWorkingcopyLocation)
    installLocalUtility(
        root, zeit.cms.content.template.TemplateManagerContainer,
        'templates', zeit.cms.content.interfaces.ITemplateManagerContainer)
    installGeneralTaskService()
    installEventTaskService()
    installLowPriorityTaskService()
    installRelations()


def evolve(context):
    zeit.cms.generation.do_evolve(context, install)

@@ -360,41 +360,8 @@
 ent%0A
-import zope.component.interfaces%0A
 impo
@@ -699,141 +699,30 @@
     
-site_manager = zope.component.getSiteManager()%0A    tasks = installLocalUtility(%0A        site_manager, lovely.remotetask.TaskS
+_install_task_s
 ervice
-, 
+(
 'tas
@@ -737,205 +737,34 @@
 al',
-%0A        lovely.remotetask.interfaces.ITaskService, utility_name='general')%0A    # Use MultiProcessor for parallel processing.%0A    tasks.processorFactory = lovely.remotetask.processor.MultiProcessor
+ 'general', max_threads=5)
 %0A%0A%0Ad
@@ -767,39 +767,32 @@
 %0A%0A%0Adef _install_
-serial_
 task_service(nam
@@ -806,16 +806,29 @@
 ity_name
+, max_threads
 ):%0A    s
@@ -1286,17 +1286,27 @@
 reads': 
-1
+max_threads
 %7D%0A%0A%0Adef 
@@ -1337,39 +1337,32 @@
 ):%0A    _install_
-serial_
 task_service('ta
@@ -1381,16 +1381,31 @@
 'events'
+, max_threads=1
 )%0A%0A%0Adef 
@@ -1454,15 +1454,8 @@
 all_
-serial_
 task
@@ -1489,16 +1489,31 @@
 lowprio'
+, max_threads=1
 )%0A%0A%0Adef 

Extract common code