"""This module contains the Redis models for the ``saba`` discrete_app."""

import json

from limpyd.fields import StringField

from mtp.apps.common.limpyd_base import DjangoBackedRedisModel

from .models import CertificationProgramUserStatusDjangoTask


class SabaLimpydTask(DjangoBackedRedisModel):
    """Redis model for the ``CertificationProgramUserStatusDjangoTask`` django model.

    It allows to store in redis the data structure holding the task completion status
    and output data.

    Attributes
    ----------
    django_model: ``django.db.models.Model`` instance
        Linked django model
    results_storage: ``limpyd.fields.StringField`` instance
        Task completion status and output data structure.
        NB: we can not call this field _results because limpyd would "ignore" it
        https://github.com/limpyd/redis-limpyd/blob/fddad21172f918a0cdc8956af8a500697851121b/limpyd/model.py#L53

    Notes
    -----
    We are not using the standard celery result backend to store the results of the task
    because we want to persist those results even in the case of a catastrophic failure
    (unmanaged exception or worker crash/halt).

    """

    django_model = CertificationProgramUserStatusDjangoTask

    results_storage = StringField()

    @property
    def results(self):
        """Helper to get json stored ``results_storage`` as dict

        Returns
        -------
        dict or None
            The python data dict if it exists, else None

        """

        results = self.results_storage.get()

        if results:
            return json.loads(results)

    @results.setter
    def results(self, data):
        """Helper to store a data dict as json in ``results_storage``

        Parameters
        ----------
        data : {dict}
            The data dict to store


        Raises
        ------
        TypeError
            If provided ``data`` is not a dict

        """

        if not isinstance(data, dict):
            raise TypeError('Instance of dict expected.')

        self.results_storage.set(json.dumps(data))
