""" Manage mentions and their attributes. """

from cort.core import mention_property_computer
from cort.core import spans

import pickle
import nltk

__author__ = 'smartschat'


class Mention:
    """ A mention is an expression in a document which is potentially referring.

    Attributes:
        document (CoNLLDocument): The document the mention belongs to.
        span (Span): The span of the mention in its document. If for example
            the span is (3, 4), then the mention starts at the 3rd token in
            the document and ends at the 4th (inclusive).
        attributes (dict(str, object)): A mapping of attribute names to
            attribute values. When creating a document from a text, The
            following attributes are used:

                - tokens (list(str)): the tokens of the mention,
                - head (list(str)): the head words of the mention,
                - pos (list(str)): the part-of-speech tags of the mention,
                - ner (list(str)): the named entity tags of the mention,
                  as found in the data,
                - type (str): the mention type, one of

                    - NAM (proper name),
                    - NOM (common noun),
                    - PRO (pronoun),
                    - DEM (demonstrative pronoun),
                    - VRB (verb),

                - fine_type (str): only set when the mention is a nominal or a
                  pronoun, for nominals values

                    - DEF (definite noun phrase) or
                    - INDEF,

                  for pronouns values

                    - PERS_NOM (personal pronoun, nominative case),
                    - PERS_ACC (personal pronoun, accusative),
                    - REFL (reflexive pronoun),
                    - POSS (possessive pronoun) or
                    - POSS_ADJ (possessive adjective, e.g. 'his'),

                - citation_form (str): only set if the mention is a pronoun,
                  then the canonical form of the pronoun, i.e. one of
                  i, you, he, she, it, we, they,
                - grammatical_function (str): either SUBJECT, OBJECT or OTHER,
                - number (str): either SINGULAR, PLURAL or UNKNOWN,
                - gender (str): either MALE, FEMALE, NEUTRAL, PLURAL or UNKNOWN,
                - semantic_class (str): either PERSON, OBJECT or UNKNOWN,
                - sentence_id (int): the sentence id of the mention's sentence
                  (starting at 0),
                - parse_tree (nltk.ParentedTree): the parse tree of the mention,
                - speaker (str): the speaker of the mention,
                - antecedent (Mention): the antecedent of the mention
                  (intially None),
                - annotated_set_id (str): the set id of the mention as found
                  in the data,
                - set_id (str): the set id of the mention computed by a
                  coreference resolution approach (initially None),
                - head_span (Span): the span of the head (in the document),
                - head_index (int): the mention-internal index of the start of
                  the head,
                - is_apposition (bool): whether the mention contains an
                  apposition,
                - head_as_lowercase_string (str): the head lowercased and as a
                  string,
                - tokens_as_lowercase_string (str): all tokens of the mention
                  lowercased and as a string,
                - first_in_gold_entity (bool): whether the mention is the first
                  mention in its gold entity (for system mentions, this is
                  also true if no preceding mention in the same entity was
                  found by the mention extractor),

    """
    def __init__(self, document, span, attributes):
        """ Initialize a mention in a document.

        Args:
            document (CoNLLDocument): The document the mention belongs to.
            span (Span): The span of the mention in its document.
            attributes (dict(str, object)): A mapping of attribute names to
                attribute values (see the class documentation for more
                information).
        """
        if document != None:
            self.document_id = document.identifier
        self.span = span
        self.attributes = attributes

    @staticmethod
    def dummy_from_document(document):

        return Mention(document, None, {
            "is_dummy": True,
            "annotated_set_id": None,
            "tokens": [],
            "first_in_gold_entity": True
        })

    def is_dummy(self):
        return "is_dummy" in self.attributes and self.attributes["is_dummy"]

    @staticmethod
    def from_document(span, document, first_in_gold_entity=False):
        """
        Create a mention from a span in a document.

        All attributes of the mention are computed from the linguistic
        information found in the document. For information about the
        attributes, see the class documentation.

        Args:
            document (CoNLLDocument): The document the mention belongs to.
            span (Span): The span of the mention in the document.

        Returns:
            Mention: A mention extracted from the input span in the input
            document.
        """

        i, sentence_span = document.get_sentence_id_and_span(span)

        subtree = mention_property_computer.get_relevant_parented_subtree(span, document)

        attributes = {
            "tokens": document.tokens[span.begin:span.end + 1],
            "pos": document.pos[span.begin:span.end + 1],
            "ner": document.ner[span.begin:span.end + 1],
            "sentence_id": i,
            "parse_tree": nltk.Tree.fromstring(str(subtree)),
            "parent_parse_tree": nltk.Tree.fromstring(str(subtree.parent())),
            "speaker": document.speakers[span.begin],