import pytest


from hgvs.exceptions import HGVSInvalidIntervalError
from hgvs.utils.cigarmapper import CIGARMapper


cigar = "3=2N=X=3N=I=D="
#  0   1   2           3   4   5               6       7   8   9  tgt
#  =   =   =   N   N   =   X   =   N   N   N   =   I   =   D   =
#  0   1   2   3   4   5   6   7   8   9  10  11  12  13      14  ref


cm = CIGARMapper(cigar)


def test_cigarmapper():
    """simple cigar test
    
    """

    assert cm.ref_len == 15
    assert cm.tgt_len == 10
    
    assert len(cm.ref_pos) == len(cm.tgt_pos)
    assert cm.ref_pos == [0, 3, 5, 6, 7, 8, 11, 12, 13, 14, 14, 15]
    assert cm.tgt_pos == [0, 3, 3, 4, 5, 6,  6,  7,  7,  8,  9, 10]

    # ref to tgt
    assert cm.map_ref_to_tgt(0,'start') == (0, 0, '=')
    assert cm.map_ref_to_tgt(0,'end') == (0, 0, '=')
    assert cm.map_ref_to_tgt(1,'start') == (1, 0, '=')
    assert cm.map_ref_to_tgt(1,'end') == (1, 0, '=')
    assert cm.map_ref_to_tgt(2,'start') == (2, 0, '=')
    assert cm.map_ref_to_tgt(2,'end') == (2, 0, '=')
    assert cm.map_ref_to_tgt(3,'start') == (2, 1, 'N')
    assert cm.map_ref_to_tgt(3,'end') == (2, 1, 'N')
    assert cm.map_ref_to_tgt(4,'start') == (3, -1, 'N')
    assert cm.map_ref_to_tgt(4,'end') == (3, -1, 'N')
    assert cm.map_ref_to_tgt(5,'start') == (3, 0, '=')
    assert cm.map_ref_to_tgt(5,'end') == (3, 0, '=')
    assert cm.map_ref_to_tgt(6,'start') == (4, 0, 'X')
    assert cm.map_ref_to_tgt(6,'end') == (4, 0, 'X')
    assert cm.map_ref_to_tgt(7,'start') == (5, 0, '=')
    assert cm.map_ref_to_tgt(7,'end') == (5, 0, '=')
    assert cm.map_ref_to_tgt(8,'start') == (5, 1, 'N')
    assert cm.map_ref_to_tgt(8,'end') == (5, 1, 'N')
    assert cm.map_ref_to_tgt(9,'start') == (5, 2, 'N')
    assert cm.map_ref_to_tgt(9,'end') == (5, 2, 'N')
    assert cm.map_ref_to_tgt(10,'start') == (6, -1, 'N')
    assert cm.map_ref_to_tgt(10,'end') == (6, -1, 'N')
    assert cm.map_ref_to_tgt(11,'start') == (6, 0, '=')
    assert cm.map_ref_to_tgt(11,'end') == (6, 0, '=')
    assert cm.map_ref_to_tgt(12,'start') == (6, 0, 'I')
    assert cm.map_ref_to_tgt(12,'end') == (7, 0, 'I')
    assert cm.map_ref_to_tgt(13,'start') == (7, 0, '=')
    assert cm.map_ref_to_tgt(13,'end') == (7, 0, '=')
    assert cm.map_ref_to_tgt(14,'start') == (9, 0, '=')
    assert cm.map_ref_to_tgt(14,'end') == (9, 0, '=')

    # tgt to ref
    assert cm.map_tgt_to_ref(0,'start') == (0, 0, '=')
    assert cm.map_tgt_to_ref(0,'end') == (0, 0, '=')
    assert cm.map_tgt_to_ref(1,'start') == (1, 0, '=')
    assert cm.map_tgt_to_ref(1,'end') == (1, 0, '=')
    assert cm.map_tgt_to_ref(2,'start') == (2, 0, '=')
    assert cm.map_tgt_to_ref(2,'end') == (2, 0, '=')
    assert cm.map_tgt_to_ref(3,'start') == (5, 0, '=')
    assert cm.map_tgt_to_ref(3,'end') == (5, 0, '=')
    assert cm.map_tgt_to_ref(4,'start') == (6, 0, 'X')
    assert cm.map_tgt_to_ref(4,'end') == (6, 0, 'X')
    assert cm.map_tgt_to_ref(5,'start') == (7, 0, '=')
    assert cm.map_tgt_to_ref(5,'end') == (7, 0, '=')
    assert cm.map_tgt_to_ref(6,'start') == (11, 0, '=')
    assert cm.map_tgt_to_ref(6,'end') == (11, 0, '=')
    assert cm.map_tgt_to_ref(7,'start') == (13, 0, '=')
    assert cm.map_tgt_to_ref(7,'end') == (13, 0, '=')
    assert cm.map_tgt_to_ref(8,'start') == (13, 0, 'D')
    assert cm.map_tgt_to_ref(8,'end') == (14, 0, 'D')
    assert cm.map_tgt_to_ref(9,'start') == (14, 0, '=')
    assert cm.map_tgt_to_ref(9,'end') == (14, 0, '=')


    
def test_cigarmapper_strict_bounds():
    # exception raised for out of bounds on left?
    with pytest.raises(HGVSInvalidIntervalError):
        cm.map_ref_to_tgt(-1, "start", strict_bounds=True)

    # ... and right?
    with pytest.raises(HGVSInvalidIntervalError):
        cm.map_ref_to_tgt(cm.ref_len + 1, "start", strict_bounds=True)

    # test whether 1 base outside bounds results in correct position
    assert ( 0, 0, '=') == cm.map_ref_to_tgt( 0, "start", strict_bounds=True)
    assert (-1, 0, '=') == cm.map_ref_to_tgt(-1, "start", strict_bounds=False)
    assert (cm.tgt_len    , 0, '=') == cm.map_ref_to_tgt(cm.ref_len,     "start", strict_bounds=True)
    assert (cm.tgt_len - 1, 0, '=') == cm.map_ref_to_tgt(cm.ref_len - 1, "start", strict_bounds=False)
    
