"""Exceptions for the ``versionable`` app."""

from django_lockable.exceptions import LockedField

__all__ = ('NotCopiable', 'NotDraftable', 'NotEditable', 'NotPublishable')


class VersionableException(Exception):
    """Base exception for the whole ``versionable`` module."""
    pass


class NotEditable(LockedField, VersionableException):
    """Exception raised when a ``Versionable`` is not in a state that permits its edition.

    The exception string exposes the string representation of the versionable instance, and its
    versionable state.

    For the other parameters see the ``LockedField`` exception class.

    """

    def __str__(self):
        """Render a useful representation of the exception."""

        from .models import Versionable

        base_message = 'The "%s" field of "%s" cannot be edited' % (
            self.attribute,
            repr(self.instance)
        )

        if isinstance(self.instance, Versionable):
            return '%s because it is in the "%s" state.' % (
                base_message,
                self.instance.get_loaded_version_state_display(),
            )
        else:
            versionable_instance = self.instance.versionable_instance
            return '%s because "%s" is in the "%s" state.' % (
                base_message,
                repr(versionable_instance),
                versionable_instance.get_loaded_version_state_display(),
            )


class NotDraftable(VersionableException):
    """Exception raised when a ``Versionable`` is not in a valid state to create a draft from it.

    The exception string exposes the string representation of the versionable instance, and its
    versionable state.

    Parameters
    ----------
    instance : Versionable
        The ``Versionable`` instance that raised the original exception.

    Attributes
    ----------
    instance : Versionable
        The instance given as parameter

    """

    def __init__(self, instance):
        """Save the given instance in the object to use in ``str``"""

        super().__init__()
        self.instance = instance

    def __str__(self):
        """Render a useful representation of the exception."""

        return 'The "%s" cannot be used to create a draft because it is in the "%s" state.' % (
            repr(self.instance),
            self.instance.get_loaded_version_state_display(),
        )


class NotCopiable(VersionableException):
    """Exception raised when a ``Versionable`` is not in a valid state to create a copy from it.

    The exception string exposes the string representation of the versionable instance, and its
    versionable state.

    Parameters
    ----------
    instance : Versionable
        The ``Versionable`` instance that raised the original exception.

    Attributes
    ----------
    instance : Versionable
        The instance given as parameter

    """

    def __init__(self, instance):
        """Save the given instance in the object to use in ``str``"""

        super().__init__()
        self.instance = instance

    def __str__(self):
        """Render a useful representation of the exception."""

        return 'The "%s" cannot be used to create a copy because it is in the "%s" state.' % (
            repr(self.instance),
            self.instance.get_loaded_version_state_display(),
        )


class NotPublishable(VersionableException):
    """Exception raised when a ``Versionable`` is not in a state that permits it to be published.

    The exception string exposes the string representation of the versionable instance, and its
    versionable state.

    Parameters
    ----------
    instance : Versionable
        The ``Versionable`` instance that raised the original exception.

    Attributes
    ----------
    instance : Versionable
        The instance given as parameter

    """

    def __init__(self, instance):
        """Save the given instance in the object to use in ``str``"""

        super().__init__()
        self.instance = instance

    def __str__(self):
        """Render a useful representation of the exception."""

        return 'The "%s" cannot be published because it is in the "%s" state.' % (
            repr(self.instance),
            self.instance.get_loaded_version_state_display(),
        )
