__author__ = 'nlw'

import logging

from dipper.models.assoc.Association import Assoc


logger = logging.getLogger(__name__)

class G2PAssoc(Assoc):
    """
    A specific association class for defining Genotype-to-Phenotype relationships
    This assumes that a graph is created outside of this class, and nodes get added.
    By default, an association will assume the "has_phenotype" relationship, unless
    otherwise specified.
    Note that genotypes are expected to be created and defined outside of this association,
    most likely by calling methods in the Genotype() class.
    """

    def __init__(self, definedby, entity_id, phenotype_id, rel=None):
        super().__init__(definedby)
        self.entity_id = entity_id
        self.phenotype_id = phenotype_id

        if rel is None:
            rel = self.properties['has_phenotype']  # default to has_phenotype

        self.start_stage_id = None
        self.end_stage_id = None
        self.environment_id = None

        self.set_subject(entity_id)
        self.set_object(phenotype_id)
        self.set_relationship(rel)

        return

    def set_stage(self, start_stage_id, end_stage_id):
        if start_stage_id is not None and start_stage_id.strip() != '':
            self.start_stage_id = start_stage_id
        if end_stage_id is not None and end_stage_id.strip() != '':
            self.end_stage_id = end_stage_id
        return

    def set_environment(self, environment_id):
        if environment_id is not None and environment_id.strip() != '':
            self.environment_id = environment_id

        return

    def set_association_id(self, assoc_id=None):

        if assoc_id is None:
            self.assoc_id = self.make_g2p_id()
        else:
            self.assoc_id = assoc_id

        return

    def add_association_to_graph(self, g):
        """
        The reified relationship between a genotype (or any genotype part) and a phenotype
        is decorated with some provenance information.
        This makes the assumption that both the genotype and phenotype are classes.

        currently hardcoded to map the annotation to the monarch namespace
        :param g:
        :return:
        """

        self._add_basic_association_to_graph(g)

        if self.start_stage_id is not None:
            self.gu.addTriple(g, self.assoc_id,
                              self.gu.object_properties['has_begin_stage_qualifier'],
                              self.start_stage_id)
        if self.end_stage_id is not None:
            self.gu.addTriple(g, self.assoc_id,
                              self.gu.object_properties['has_end_stage_qualifier'],
                              self.end_stage_id)

        if self.environment_id is not None:
            self.gu.addTriple(g, self.assoc_id,
                              self.gu.object_properties['has_environment_qualifier'],
                              self.environment_id)
        return g

    def make_g2p_id(self):
        """
        Make an association id for phenotypic associations that is defined by:
            source of association + (Annot subject) + relationship + phenotype/disease
                + environment + start stage + end stage
        :return:
        """

        attributes = [self.environment_id, self.start_stage_id, self.end_stage_id]
        assoc_id = self.make_association_id(self.definedby, self.entity_id, self.rel, self.phenotype_id, attributes)

        return assoc_id
@@ -27,16 +27,26 @@
  logging
+%0Aimport re
 %0A%0Afrom d
@@ -593,24 +593,95 @@
 s.%0A    %22%22%22%0A%0A
+    g2p_types = %7B%0A        'developmental_process': 'GO:0032502'%0A    %7D%0A%0A
     def __in
@@ -2327,16 +2327,45 @@
 aph(g)%0A%0A
+        # make a blank stage%0A
         
@@ -2379,32 +2379,53 @@
 .start_stage_id 
+or self.end_stage_id 
 is not None:%0A   
@@ -2438,38 +2438,390 @@
    s
-elf.gu.addTriple(g, self.assoc
+tage_process_id = '-'.join((str(self.start_stage_id), str(self.end_stage_id)))%0A            stage_process_id = '_'+re.sub(':', '', stage_process_id)%0A            # TODO deal with nobnodes%0A            self.gu.addIndividualToGraph(g, stage_process_id, None,%0A                                         self.g2p_types%5B'developmental_process'%5D)%0A            self.gu.addTriple(g, stage_process
 _id,
@@ -2882,33 +2882,21 @@
 es%5B'
-has_begin_stage_qualifier
+starts_during
 '%5D,%0A
@@ -2958,89 +2958,171 @@
     
-if
+   
  self.
-end_stage_id is not None:%0A            self.gu.addTriple(g, self.assoc_id,
+gu.addTriple(g, stage_process_id,%0A                              self.gu.object_properties%5B'ends_during'%5D,%0A                              self.end_stage_id)
 %0A   
@@ -3130,33 +3130,105 @@
         
-                 
+self.stage_process_id = stage_process_id%0A%0A            self.gu.addTriple(g, self.assoc_id,
  self.gu
@@ -3251,26 +3251,16 @@
 es%5B'has_
-end_stage_
 qualifie
@@ -3295,34 +3295,38 @@
        self.
-end_
 stage_
+process_
 id)%0A%0A       
@@ -3471,28 +3471,16 @@
 es%5B'has_
-environment_
 qualifie

refactor how stages are included in G2P Assoc