from dataclasses import dataclass
from enum import Enum
from typing import Optional, Any


@dataclass
class ORMEntityType:
    id: str
    name: str
    ref_mode: Optional[str]


@dataclass
class ORMValueType:
    id: str
    name: str
    data_type: str


@dataclass
class ORMRole:
    id: str
    name: str
    relationship_name: str
    player: str


@dataclass
class ORMSubtypeFact:
    subtype_role_id: Optional[str]
    subtype: Optional[str]
    supertype_role_id: Optional[str]
    supertype: Optional[str]


@dataclass
class SubtypeFact:
    subtype_name: str
    supertype_name: str


@dataclass
class ExclusiveSubtypeFact(SubtypeFact):
    pass


@dataclass
class ExclusiveInclusiveSubtypeFact(SubtypeFact):
    pass


@dataclass
class ORMUniquenessConstraint:
    id: str
    roles: list[str]
    identifies: Optional[str]


@dataclass
class ORMMandatoryConstraint:
    id: str
    roles: list[str]


@dataclass
class ORMRingConstraint:
    id: str
    roles: list[str]
    ring_types: list['ORMRingType']


class ORMRingType(Enum):
    IRREFLEXIVE = 'Irreflexive'
    ANTISYMMETRIC = 'Antisymmetric'
    ASYMMETRIC = 'Asymmetric'
    STRONGLY_INTRANSITIVE = 'StronglyIntransitive'
    INTRANSITIVE = 'Intransitive'
    ACYCLIC = 'Acyclic'
    PURELY_REFLEXIVE = 'PurelyReflexive'
    REFLEXIVE = 'Reflexive'
    SYMMETRIC = 'Symmetric'
    TRANSITIVE = 'Transitive'


@dataclass
class ORMExclusionConstraint:
    id: str
    roles: list[str]
    inclusive: bool


@dataclass
class ORMInclusionConstraint:
    id: str
    roles: list[str]
    exclusive: bool


@dataclass
class ORMReadingOrder:
    roles: list['ORMReadingOrderRole']


@dataclass
class ORMReadingOrderRole:
    index: int
    prefix: Optional[str]
    postfix: Optional[str]
    text: Optional[str]
    role: Optional[ORMRole]


@dataclass
class ORMRoleValueConstraint:
    role: ORMRole
    values: list[Any]


@dataclass
class RoleConstraint:
    roles: list[str]
    inclusive: bool
    exclusive: bool
