package org.biojava3.alignment.routines;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import java.util.ArrayList;
import java.util.List;

import org.biojava3.alignment.routines.AlignerHelper.Anchor;
import org.biojava3.alignment.routines.AlignerHelper.Cut;
import org.biojava3.alignment.routines.AlignerHelper.Subproblem;
import org.junit.Test;

/**
 * 
 * @author Daniel Cameron
 *
 */
public class AlignerHelperTest {
	@Test
	public void getCuts_should_not_return_start_position_for_starting_anchor() {
		Cut[] cuts = AlignerHelper.getCuts(10, new Subproblem(5, 20, 10, 30), new int[] { 50, 50, 3 }, true);
		assertNotEquals(5, cuts[0].getQueryIndex());
	}
	@Test
	public void getCuts_should_return_all_positions_when_cuts_exceeds_query_size() {
		Cut[] cuts = AlignerHelper.getCuts(10, new Subproblem(5, 20, 10, 30), new int[] { 50, 50, 3 }, false);
		assertEquals(5, cuts.length);
		assertEquals(5, cuts[0].getQueryIndex());
		assertEquals(6, cuts[1].getQueryIndex());
		assertEquals(7, cuts[2].getQueryIndex());
		assertEquals(8, cuts[3].getQueryIndex());
		assertEquals(9, cuts[4].getQueryIndex());
	}
	@Test
	public void getCuts_should_return_spaced_cuts_when_query_interval_larger_than_cut_size() {
		Cut[] cuts = AlignerHelper.getCuts(3, new Subproblem(5, 20, 10, 30), new int[] { 50, 50, 3 }, false);
		assertEquals(3, cuts.length);
		assertEquals(5, cuts[0].getQueryIndex());
		assertEquals(7, cuts[1].getQueryIndex());
		assertEquals(9, cuts[2].getQueryIndex());
	}
	@Test
	public void getSubproblems_should_return_score_indicies_of_alignment_subproblems() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		anchors.add(new Anchor(1, 2));
		anchors.add(new Anchor(5, 5));
		List<Subproblem> problems = AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
		assertEquals(3, problems.size());
		assertEquals(0, problems.get(0).getQueryStartIndex());
		assertEquals(0, problems.get(0).getTargetStartIndex());
		assertEquals(1, problems.get(0).getQueryEndIndex());
		assertEquals(2, problems.get(0).getTargetEndIndex());
		assertEquals(2, problems.get(1).getQueryStartIndex());
		assertEquals(3, problems.get(1).getTargetStartIndex());
		assertEquals(5, problems.get(1).getQueryEndIndex());
		assertEquals(5, problems.get(1).getTargetEndIndex());
		assertEquals(6, problems.get(2).getQueryStartIndex());
		assertEquals(6, problems.get(2).getTargetStartIndex());
		assertEquals(10, problems.get(2).getQueryEndIndex());
		assertEquals(15, problems.get(2).getTargetEndIndex());
	}
	@Test
	public void getSubproblems_should_allow_zero_anchors() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		List<Subproblem> problems = AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
		assertEquals(1, problems.size());
		assertEquals(0, problems.get(0).getQueryStartIndex());
		assertEquals(0, problems.get(0).getTargetStartIndex());
		assertEquals(10, problems.get(0).getQueryEndIndex());
		assertEquals(15, problems.get(0).getTargetEndIndex());
		assertEquals(false, problems.get(0).isStartAnchored());
	}
	@Test
	public void getSubproblems_should_allow_start_and_end_anchors() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		anchors.add(new Anchor(0, 0));
		anchors.add(new Anchor(9, 14));
		List<Subproblem> problems = AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
		assertEquals(3, problems.size());
		assertEquals(0, problems.get(0).getQueryStartIndex());
		assertEquals(0, problems.get(0).getTargetStartIndex());
		assertEquals(0, problems.get(0).getQueryEndIndex());
		assertEquals(0, problems.get(0).getTargetEndIndex());
		assertEquals(false, problems.get(0).isStartAnchored());
		assertEquals(1, problems.get(1).getQueryStartIndex());
		assertEquals(1, problems.get(1).getTargetStartIndex());
		assertEquals(9, problems.get(1).getQueryEndIndex());
		assertEquals(14, problems.get(1).getTargetEndIndex());
		assertEquals(true, problems.get(1).isStartAnchored());
		assertEquals(10, problems.get(2).getQueryStartIndex());
		assertEquals(15, problems.get(2).getTargetStartIndex());
		assertEquals(10, problems.get(2).getQueryEndIndex());
		assertEquals(15, problems.get(2).getTargetEndIndex());
		assertEquals(true, problems.get(2).isStartAnchored());
	}
	@Test
	public void getSubproblems_should_allow_adjacent_anchors() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		anchors.add(new Anchor(1, 1));
		anchors.add(new Anchor(2, 3));
		List<Subproblem> problems = AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
		assertEquals(3, problems.size());
		assertEquals(2, problems.get(1).getQueryStartIndex());
		assertEquals(2, problems.get(1).getTargetStartIndex());
		assertEquals(2, problems.get(1).getQueryEndIndex());
		assertEquals(3, problems.get(1).getTargetEndIndex());
		assertEquals(3, problems.get(2).getQueryStartIndex());
		assertEquals(4, problems.get(2).getTargetStartIndex());
		assertEquals(10, problems.get(2).getQueryEndIndex());
		assertEquals(15, problems.get(2).getTargetEndIndex());
	}
	@Test(expected=IllegalArgumentException.class)
	public void getSubproblems_should_not_allow_repeated_anchors() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		anchors.add(new Anchor(1, 1));
		anchors.add(new Anchor(1, 2));
		AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
	}
	@Test(expected=IllegalArgumentException.class)
	public void getSubproblems_should_not_allow_unalignable_anchors() {
		List<Anchor> anchors = new ArrayList<Anchor>();
		anchors.add(new Anchor(1, 2));
		anchors.add(new Anchor(2, 1));
		AlignerHelper.Subproblem.getSubproblems(anchors, 10, 15);
	}
}
