import os

from pickle import load, dump

from types import MethodType

import sys
import logging

from ve.config import data237_paraepi_cache as cache_dir

from common import make_logger
logger = make_logger("Paratope Epitope Detection")

#cache utility
from ve.fp.complex_util.cache import ParatopeCache as PCache, EpitopeCache as ECache

#solving trait dependency issue
from ve.fp.complex_util.propagate_distcache import DistanceCachePropagationTrait

class ParatopeNotFoundError(Exception):pass
class EpitopeNotFoundError(Exception):pass

class FindParaEpiTrait(DistanceCachePropagationTrait):
    """
    find epitope and paratope trait
    
    Dependency:
    1. dist cache propagation
    """
"""
Propagate the complex's distance matrix cache to all its residues
"""
from itertools import chain
from types import MethodType

from ve.util.dist import ResDistCache

from common import make_logger
logger = make_logger("Distance Cache Propagation")

class DistanceCachePropagationTrait(object):
    """
    Distance cache needs to be populated to residues
    propagate the distance matrix cache to all the subordinating residues
    """
    def __init__(self, cache_cls = ResDistCache):
        super(DistanceCachePropagationTrait,self).__init__()
        self.distcache = cache_cls()

        self.prop_dist_cache()
        
    def prop_dist_cache(self):
        """
        propagate the distance matrix cache to all the subordinating residues
        """
        logger.debug("propagating distance cache to residues")
        for r in chain(self.atg.residues, self.atb.residues):
            r.distcache = self.distcache
"""
def init_propagate_distcache_trait(self, cache_cls = ResDistCache):
from ve.fp.residue_util.res_triangle import ResTriangle

from ve.fp.complex_util.paraepi import FindParaEpiTrait
from types import MethodType

from common import make_logger
logger = make_logger("Residue Triangle Detection")

from ve.fp.complex_util.cache import TriangleCache as cache

class ResidueTriangleTrait(FindParaEpiTrait):
    """
    find triangles in the epitope part of the complex.

    Dependency:
    1, epitope finding trait
    """
    def get_triangles(self, refresh = False):
        #cached in memory already
        if hasattr(self, "triangles"):
            return self.triangles
            
        #cached in local file already
        if not refresh and cache.has_cache(self.c_id):
            self.triangles = cache.load(self.c_id, self)
            assert(len(self.triangles) != 0)
            return self.triangles
            
        #stores residue tuples that are possible to form triangle with external residue
        still_possible_pairs = []