"""
:mod:`zsl.interface.celery.worker`
----------------------------------

Implementation of celery workers.

.. moduleauthor:: Peter Morihladko
"""
from __future__ import unicode_literals

import sys

from celery import Celery, shared_task
from injector import Module, singleton, provides

from zsl import Config
from zsl.utils.injection_helper import inject
from zsl.interface.task_queue import TaskQueueWorker
from zsl.task.job_context import Job


class CeleryTaskQueueWorkerBase(TaskQueueWorker):
    """Base class for celery task queue worker.

    It initialize the celery app in constructor.
    """

    @inject(config=Config)
    def __init__(self, config):
        # type: (Config) -> None
        super(CeleryTaskQueueWorkerBase, self).__init__()

        self.celery_app = Celery()
        self.celery_app.config_from_object(config['CELERY'])

    def execute_celery_task(self, job_data):
        # type: (dict) -> dict
        """Creates job from task and executes the job.

        :param job_data: job's data
        :return: job results
        :rtype: dict
        """
        job = Job(job_data)

        return self.execute_job(job)


class CeleryTaskQueueOutsideWorker(CeleryTaskQueueWorkerBase):
    """Celery worker used only for task execution.

    This can be used when the worker is manage with some other application,
    like `celery worker` or `celery multi`.
    """

    def stop_worker(self):
        self._app.logger.error("Running from celery worker, kill from shell!")

    def run(self):
        self._app.logger.error("Running from celery worker, start from shell!")


class CeleryTaskQueueMainWorker(CeleryTaskQueueWorkerBase):
    """Worker implementation for Celery task queue.
    """
    def __init__(self):
        super(CeleryTaskQueueMainWorker, self).__init__()

        self.celery_worker = None

    def stop_worker(self):
        self._app.logger.info("Stopping Celery worker on demand - quitting.")
        self.celery_worker.stop()

    def run(self, argv, *args, **kwargs):
        self._app.logger.info("Running the worker.")
        self.celery_worker = self.celery_app.worker_main((sys.argv[0],) + argv)


class CeleryTaskQueueMainWorkerModule(Module):
    """Injector module for celery main worker."""
    @singleton
    @provides(CeleryTaskQueueWorkerBase)
    def provide_worker(self):
        return CeleryTaskQueueMainWorker()


class CeleryTaskQueueOutsideWorkerModule(Module):
    """Injector module for celery outside worker."""
    @singleton
    @provides(CeleryTaskQueueWorkerBase)
    def provide_worker(self):
        return CeleryTaskQueueMainWorker()


@shared_task
@inject(worker=CeleryTaskQueueWorkerBase)
def zsl_task(job_data, worker):
    # type: (dict, CeleryTaskQueueWorkerBase) -> dict
    """This function will be registered as a celery task.

    :param job_data: task data
    :param worker: current celery worker
    :type worker: CeleryTaskQueueWorkerBase
    :return: task results
    """
    return worker.execute_celery_task(job_data)


@@ -288,31 +288,8 @@
 es%0A%0A
-from zsl import Config%0A
 from
@@ -330,16 +330,16 @@
  inject%0A
+
 from zsl
@@ -532,305 +532,64 @@
  It 
-initialize the celery app in constructor.%0A    %22%22%22%0A%0A    @inject(config=Config)%0A    def __init__(self, config):%0A        # type: (Config) -%3E None%0A        super(CeleryTaskQueueWorkerBase, self).__init__()%0A%0A        self.celery_app = Celery()%0A        self.celery_app.config_from_object(config%5B'CELERY'%5D)
+contains only the task execution part of worker.%0A    %22%22%22
 %0A%0A  
@@ -1447,25 +1447,21 @@
 k queue.
-%0A    
 %22%22%22%0A
+%0A
     def 
@@ -1469,24 +1469,25 @@
 _init__(self
+,
 ):%0A        s
@@ -1532,24 +1532,126 @@
 __init__()%0A%0A
+        self.celery_app = Celery()%0A        self.celery_app.config_from_object(self._config%5B'CELERY'%5D)%0A
         self

Remove the celery app from the CeleryWorkerBase