from nose.tools import raises

from sqt.cigar import parse, Cigar, reference_to_query_length

def test_parse():
	# deprecated
	assert parse("4S17M8D4M9I3H") == [(4, 4), (0, 17), (2, 8), (0, 4), (1, 9), (5, 3)]


def test_cigar_class():
	assert Cigar('') == Cigar([])
	assert Cigar('4M') == Cigar([(0, 4)])
	c = Cigar('4S 17M 8D 4M 9I 3H')
	assert str(c) == '4S17M8D4M9I3H'
	assert '{}'.format(c) == str(c)
	assert '{: }'.format(c) == '4S 17M 8D 4M 9I 3H'
	assert repr(c) == "Cigar('4S17M8D4M9I3H')"
	assert Cigar('4M') + Cigar('1D') == Cigar('4M 1D')
	assert Cigar('2S 4M') + Cigar('3M') == Cigar('2S 7M')
	assert Cigar('3M2S')._as_string(join_by=' ') == '3M 2S'


@raises(ValueError)
def test_parse_error_1():
	Cigar("4S5")


@raises(ValueError)
def test_parse_error_2():
	Cigar("4S-5M")


@raises(ValueError)
def test_parse_error_3():
	Cigar("M")


def test_elements():
	assert ''.join(Cigar("3S2I3M").elements()) == "SSSIIMMM"
	assert list(Cigar("3S2I3M").elements(numbers=True)) == [
		4, 4, 4, 1, 1, 0, 0, 0]


def test_length():
	c = Cigar('3H 2S 5M 1I 2M 3D 2M 4S 5H')
	assert c.query_length(count_clipped=None) == 10
	assert c.query_length(count_clipped='soft') == 16
	assert c.query_length(count_clipped='hard') == 24

	assert c.reference_length() == 12

def test_concat():
	assert Cigar('2S1M') + Cigar('3M4S') == Cigar('2S4M4S')
	assert Cigar('') + Cigar('3M4S') == Cigar('3M4S')
	assert Cigar('4S3M') + Cigar('') == Cigar('4S3M')


def test_split_at_element():
	assert Cigar('1M').split_at_element(0, 0) == (Cigar(), Cigar('1M'))
	assert Cigar('1M').split_at_element(0, 1) == (Cigar('1M'), Cigar())
	assert Cigar('2S4M4S').split_at_element(1, 1) == (Cigar('2S1M'), Cigar('3M4S'))
	assert Cigar('3M 1D 6M 2I 4M').split_at_element(2, 5) == (Cigar('3M 1D 5M'), Cigar('1M 2I 4M'))
	assert Cigar('4M 3D 5M').split_at_element(1, 0) == (Cigar('4M'), Cigar('3D 5M'))
	assert Cigar('4M 3D 5M').split_at_element(1, 1) == (Cigar('4M 1D'), Cigar('2D 5M'))
	assert Cigar('4M 3D 5M').split_at_element(1, 3) == (Cigar('4M 3D'), Cigar('5M'))


def test_reference_to_query_position():
	cig = parse('2H 2S 2M 2D 2M 2I 2M 2S 2H')
	def r2q(length):
		return reference_to_query_length(cig, length)
	assert r2q(0) == 4   # 2H 2S
	assert r2q(1) == 5   # 2H 2S 1M
	assert r2q(2) == 6   # 2H 2S 2M
	assert r2q(3) == 6   # 2H 2S 2M 1D
	assert r2q(4) == 6   # 2H 2S 2M 2D
	assert r2q(5) == 7   # 2H 2S 2M 2D 1M
	assert r2q(6) == 8   # 2H 2S 2M 2D 2M
	assert r2q(7) == 11  # 2H 2S 2M 2D 2M 2I 1M
	assert r2q(8) == 12  # 2H 2S 2M 2D 2M 2I 2M
	assert r2q(9) is None


def test_clipping():
	cig = Cigar('3S 2M 2D 2M 2I 2M 7S')
	assert cig.hard_clipping_left == 0
	assert cig.soft_clipping_left == 3
	assert cig.clipping_left == 3

	assert cig.hard_clipping_right == 0
	assert cig.soft_clipping_right == 7
	assert cig.clipping_right == 7

	cig = Cigar('2H 3S 2M 2D 2M 2I 2M 7S 11H')
	assert cig.hard_clipping_left == 2
	assert cig.soft_clipping_left == 0  # ??? or 4
	assert cig.clipping_left == 5

	assert cig.hard_clipping_right == 11
	assert cig.soft_clipping_right == 0
	assert cig.clipping_right == 18

