"""
Convenience wrappers for Celery tasks providing async jobs for Plone Intranet.

These wrappers provide authentication and serialization for easy calling.

If you want to add a task, add the business logic here, create a celery
task hook in ploneintranet.asynctasks.celerytasks and point to that task in your
own task class.
"""

from plone import api
from ploneintranet.asynctasks import celerytasks
from ploneintranet.asynctasks.core import AbstractPost
from ploneintranet.asynctasks.interfaces import IAsyncTask
from Products.CMFCore.interfaces import IIndexQueueProcessor
from zope.component import getSiteManager
from zope.interface import implementer

import logging

logger = logging.getLogger(__name__)


def index_to_solr(obj):
    """Helper method to trigger only the solr index"""
    catalog = api.portal.get_tool("portal_catalog")
    valid_indexes = list(catalog._catalog.indexes.keys())
    sm = getSiteManager()
    utilities = list(sm.getUtilitiesFor(IIndexQueueProcessor))
    util = dict(utilities).get("pisolr")
    if util is None:
        return
    util.begin()
    util.index(obj, attributes=valid_indexes)
    util.commit()


@implementer(IAsyncTask)
class Post(AbstractPost):
    """
    Execute a HTTP POST request asynchronously via Celery.
    See core.AbstractPost for implementation specifics.

    Example usage::

      url = '@@async-checktask'
      data = dict(checksum=random.random())
      try:
          post = Post(self.context, self.request)  # __init__
          post(url, data)                          # __call__
      except redis.exceptions.ConnectionError:
          return self.fail("post", "redis not available")
    """

    task = celerytasks.post
    url = None


@implementer(IAsyncTask)
class GeneratePDF(AbstractPost):
    """
    Make an HTTP request to the DocConv Plone instance to generate a PDF
    for the given object URL and add it to the object.

    Usage::

      from ploneintranet.asynctasks.tasks import GeneratePDF
      GeneratePDF(self.context, self.request)(countdown=10)

    Mind the final call parentheses.

    """

    task = celerytasks.generate_pdf
    url = "/@@generate-pdf"

    def __init__(self, context, request):
        """Add a request to sync the DB after the task is run"""
        super().__init__(context, request)
        self.headers["X-ploneintranet-docconv-client-sync-db"] = "1"
        purge = self.request.get("purge")
        if purge:
            self.data["purge"] = purge


@implementer(IAsyncTask)
class GeneratePoster(AbstractPost):
    """Like generate pdf but for videos"""

    task = celerytasks.generate_poster
    url = "@@generate-poster"

    def __init__(self, context, request=None):
        """Add a request to sync the DB after the task is run"""
        super().__init__(context, request)
        self.headers["X-ploneintranet-docconv-client-sync-db"] = "1"


@implementer(IAsyncTask)
class GenerateLeadImage(AbstractPost):
    """Like generate poster but for video links"""

    task = celerytasks.generate_lead_image
    url = "@@generate-lead-image"

    def __init__(self, context, request=None):
        """Add a request to sync the DB after the task is run"""
        super().__init__(context, request)
        self.headers["X-ploneintranet-docconv-client-sync-db"] = "1"


@implementer(IAsyncTask)
class ReindexObject(AbstractPost):
    """Reindex an object asynchronously.

    Usage:

      from ploneintranet.asynctasks.tasks import ReindexObject
      ReindexObject(self.context, self.request)()

    Mind the final call parentheses.
    """

    task = celerytasks.reindex_object
    url = "/@@reindex_object"


@implementer(IAsyncTask)
class ReindexObjectSolr(AbstractPost):
    """Reindex an object asynchronously to solr only.

    Usage:

      from ploneintranet.asynctasks.tasks import ReindexObjectSolr
      ReindexObjectSolr(self.context, self.request)()

    Mind the final call parentheses.
    """

    task = celerytasks.reindex_object_solr
    url = "/@@reindex_object_solr"


@implementer(IAsyncTask)
class ReindexRecursive(AbstractPost):
    """Reindex an object and its children asynchronously.

    Usage:

      from ploneintranet.asynctasks.tasks import ReindexRecursive
      ReindexRecursive(self.context, self.request)()

    Mind the final call parentheses.
    """

    task = celerytasks.reindex_object
    url = "/@@solr-maintenance/reindex"


@implementer(IAsyncTask)
class MarkRead(AbstractPost):
    """Asynchronously perform a hit on @@mustread-hit.

    Usage:

      from ploneintranet.asynctasks.tasks import MarkRead
      MarkRead(self.context, self.request)()

    Mind the final call parentheses.
    """

    task = celerytasks.mark_read
    url = "@@mustread-hit"


@implementer(IAsyncTask)
class ReindexObjectedSecurityForShared(AbstractPost):
    """Asynchronously perform a hit on @@mustread-hit.

    Usage:

      from ploneintranet.asynctasks.tasks import ReindexObjectedSecurityForShared
      ReindexObjectedSecurityForShared(self.context, self.request)()

    Mind the final call parentheses.
    """

    task = celerytasks.reindex_related_events_security
    url = "@@reindex_related_events_security"
