"""Some mixin classes for index table clreation"""

from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy import Column, Integer, String, Float, ForeignKey, Sequence
from sqlalchemy.orm import relationship


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class TermIndexLookupMixin(object):
    """A representation mixin for the ``term_index_lookup`` table.

    Parameters
    ----------
    token_id : `int`
        Auto-incremented primary key.
    token_str : `str`
        The actual lookup string of the token.
    token_count `int`
        The total count of the token in the dataset.
    token_prob : `int`
        The prbability that the token is encountered in the dataset.
    token_index_map : `TermIndexMap`
        The relationship back to the ``token_index_map`` table.
    """

    token_id = Column(
        Integer,
        Sequence("token_id_seq"),
        nullable=False,
        primary_key=True,
        autoincrement=True,
        doc="Auto-incremented primary key.",
    )
    token_str = Column(
        String(255),
        nullable=False,
        index=True,
        doc="The actual lookup string of the token.",
    )
    token_count = Column(
        Integer,
        nullable=False,
        doc="The total count of the token in the dataset.",
    )
    token_prob = Column(
        Float,
        nullable=False,
        doc="The prbability that the token is encountered in the dataset.",
    )

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @declared_attr
    def __tablename__(cls):
        return "term_index_lookup"

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @declared_attr
    def token_index_map(cls):
        return relationship(
            "TermIndexMap",
            back_populates="token_index_lookup",
            doc="The relationship back to the ``token_index_map`` table.",
        )


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class _TermIndexMapMixin(object):
    """A representation of the ``term_index_mapping`` table. This base mixin
    should not be used directly.

    Parameters
    ----------
    mapping_id : `int`
        Auto-incremented primary key.
    token_id : `int`
        A mapping back to a specific token.
    start_pos : `int`
        The start position of the word represented by the token in the term
        string.
    end_pos : `int`
        The end position of the word represented by the token in the term
        string.
    rank_order : `int`
        The rank order position of the word represented by the token in the
        term string.
    term_len : `int`
        The length of the unprocessed term.
    token_index_lookup : `TermIndexLookup`
        The relationship back to the ``token_index_lookup`` table.
    """

    mapping_id = Column(
        Integer,
        Sequence("mapping_id_seq"),
        nullable=False,
        primary_key=True,
        autoincrement=True,
        doc="Auto-incremented primary key.",
    )
    start_pos = Column(
        Integer,
        nullable=False,
        doc="The start position of the word represented by the token in the"
        " term string.",
    )
    end_pos = Column(
        Integer,
        nullable=False,
        doc="The end position of the word represented by the token in the"
        " term string.",
    )
    rank_order = Column(
        Integer,
        nullable=False,
        doc="The rank order position of the word represented by the token"
        " in the term string.",
    )
    term_len = Column(
        Integer,
        nullable=False,
        doc="The length of the term that the token is embedded in.",
    )

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @declared_attr
    def __tablename__(cls):
        return "term_index_mapping"

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @declared_attr
    def token_id(cls):
        return Column(
            Integer,
            ForeignKey("term_index_lookup.token_id"),
            nullable=False,
            doc="A mapping back to a specific token.",
        )

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @declared_attr
    def token_index_lookup(cls):
        return relationship(
            "TermIndexLookup",
            back_populates="token_index_map",
            doc="The relationship back to the ``token_index_lookup`` table.",
        )


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class TermIndexMapMixinInt(_TermIndexMapMixin):
    """A representation of the ``term_index_mapping`` table. This mixin
    implements the ``term_id`` as an integer.

    Parameters
    ----------
    mapping_id : `int`
        Auto-incremented primary key.
    token_id : `int`
        A mapping back to a specific token.
    start_pos : `int`
        The start position of the word represented by the token in the term
        string.
    end_pos : `int`
        The end position of the word represented by the token in the term
        string.
    rank_order : `int`
        The rank order position of the word represented by the token in the
        term string.
    term_len : `int`
        The length of the unprocessed term.
    term_id : `int`
        The ID for the term identifier.
    token_index_lookup : `TermIndexLookup`
        The relationship back to the ``token_index_lookup`` table.
    """

    term_id = Column(
        Integer,
        nullable=False,
        index=True,
        doc="The ID for the term identifier.",
    )


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class TermIndexMapMixinStr(_TermIndexMapMixin):
    """A representation of the ``term_index_mapping`` table. This mixin
    implements the ``term_id`` as a string.

    Parameters
    ----------
    mapping_id : `int`
        Auto-incremented primary key.
    token_id : `int`
        A mapping back to a specific token.
    start_pos : `int`
        The start position of the word represented by the token in the term
        string.
    end_pos : `int`
        The end position of the word represented by the token in the term
        string.
    rank_order : `int`
        The rank order position of the word represented by the token in the
        term string.
    term_len : `int`
        The length of the unprocessed term.
    term_id : `str`
        The ID for the term identifier.
    token_index_lookup : `TermIndexLookup`
        The relationship back to the ``token_index_lookup`` table.
    """

    term_id = Column(
        String(255),
        nullable=False,
        index=True,
        doc="The ID for the term identifier.",
    )
