"""This cube handles classification schemes.

:organization: Logilab
:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
from yams.buildobjs import EntityType, RelationType, SubjectRelation, String

from cubicweb import _
from cubicweb.schema import RQLConstraint


class Classification(EntityType):
    """classification schemes are used by users to classify entities."""

    __permissions__ = {
        "read": ("managers", "users", "guests"),
        "add": ("managers",),
        "delete": ("managers",),
        "update": ("managers",),
    }
    name = String(required=True, fulltextindexed=True, unique=True, maxsize=128)
    classifies = SubjectRelation(
        "CWEType",
        # see relation type docstring
        constraints=[
            RQLConstraint(
                "RDEF to_entity O," "RDEF relation_type R," 'R name "applied_to"',
                msg="Classification is trying to classifies an EntityType "
                "without applied_to relation",
            )
        ],
    )


class classifies(RelationType):
    """entity types classified by the classification. Only entity type
    supporting the applied_to relation can be selectioned
    """


class Keyword(EntityType):
    """A keyword is like a tag but is application specific
    and used to define a classification scheme
    """

    __permissions__ = {
        "read": ("managers", "users", "guests"),
        "add": ("managers", "users"),
        "delete": ("managers",),
        "update": ("managers",),
    }
    name = String(required=True, fulltextindexed=True, indexed=True, maxsize=128)

    subkeyword_of = SubjectRelation(
        "Keyword",
        cardinality="?*",
        description=_("which keyword (if any) this keyword specializes"),
        # if no included_in set, it'll be automatically added by a hook
        constraints=[
            RQLConstraint(
                "NOT S included_in CS1 OR EXISTS(S included_in CS2, O included_in CS2)"
            )
        ],
    )
    descendant_of = SubjectRelation("Keyword")
    included_in = SubjectRelation("Classification", cardinality="1*")


class CodeKeyword(Keyword):
    """A CodeKeyword is a keyword with a code and a name"""

    __specializes_schema__ = True
    code = String(required=True, fulltextindexed=True, indexed=True, maxsize=128)


class subkeyword_of(RelationType):
    """a keyword can specialize another keyword"""


class included_in(RelationType):
    """a keyword is included in a classification scheme"""

    inlined = True


# define in parent application which entity types may be linked to a keyword
# by the applied_to relation


class applied_to(RelationType):
    """tagged objects"""

    fulltext_container = "object"
    constraints = [RQLConstraint("S included_in CS, O is ET, CS classifies ET")]
