from phaser import rsam

from iotbx import bioinformatics

def alignment_search(residues, alignments, min_length, mm_type, logger):
    
    one_letter_for = dict(
        zip( mm_type.three_letter_codes, mm_type.one_letter_codes )
        )
    
    for alo in alignments:
        logger.info( "Trying %s..." % alo.name )
        ( index, rmap ) = rsam.map_to_alignment(
            alignment = alo.object,
            residues = residues,
            consecutivity = mm_type.consecutivity,
            one_letter_for = one_letter_for,
            min_length = min_length
            )
        
        if index < 0:
            logger.info( "No match, discarded" )
            continue
        
        master = alo.object.alignments[0]
        seq = alo.object.alignments[ index ]
        assert len( seq ) == len( rmap ), "len( %s ) != len( %s )" % ( seq, rmap )
        
        logger.info( "Matching sequence found!" ) 
        logger.info( "Mapping to master:" )
        pairwise = bioinformatics.clustal_alignment(
            alignments = [ master, seq ],
            names = [ "MASTER", "CURRENT" ], 
            )
        logger.info( str( pairwise ) )
        
        return ( alo.object, index, rmap )
        
    else:
        raise RuntimeError, "No matching alignment found"


def log_residues(residues):
    
    for r in residues:
        logger.debug( "Chain %s, residue %s" % ( r.parent().id, r.resid() ) )
            
    logger.info( "Altogether %s residues" % len( residues ) )
        
        
def create_alignment(seq_a, seq_b, name_a, name_b):
    
    import mmtbx.alignment
    
    align_obj = mmtbx.alignment.align( seq_a = seq_a, seq_b = seq_b )
    tmp = align_obj.extract_alignment()
    ali = bioinformatics.clustal_alignment(
        alignments = [ tmp.a, tmp.b ],
        names = [ name_a, name_b ]
        )
    return ali


def rank_sequences_by_match(trial, collection, logger):
    
    scored = []
    logger.info( "Scoring alignment sequences..." ) 
    
    for m in collection:
        ali = create_alignment( first = trial, second = m[0] )
        scored.append( ( m, ali, ali.identity_count() ) )
        
    scored.sort( key = lambda a: a[2], reverse = True )
    return scored

