package triangle;

import static org.junit.Assert.*;

import org.junit.Test;

import exception.TriangleException;

import triangle.Triangle;
import triangle.Triangle.Angle;
import triangle.Triangle.Type;

public class TestTriangle {

	/**
	 * Test de la création d'un triangle plat.
	 */
	@Test(expected = TriangleException.class)
	public void flatTriangle1() throws TriangleException {
		new Triangle(1, 1, 2);
	}

	/**
	 * Test de la création d'un triangle plat.
	 */
	@Test(expected = TriangleException.class)
	public void flatTriangle2() throws TriangleException {
		new Triangle(2, 1, 1);
	}

	/**
	 * Test de la création d'un triangle plat.
	 */
	@Test(expected = TriangleException.class)
	public void flatTriangle3() throws TriangleException {
		new Triangle(1, 2, 1);
	}

	/**
	 * Test de la création d'un triangle avec des longueurs invalides.
	 */
	@Test(expected = TriangleException.class)
	public void notATriangle1() throws TriangleException {
		new Triangle(1, 2, 8);
	}

	/**
	 * Test de la création d'un triangle avec des longueurs invalides.
	 */
	@Test(expected = TriangleException.class)
	public void notATriangle2() throws TriangleException {
		new Triangle(8, 1, 2);
	}

	/**
	 * Test de la création d'un triangle avec des côtés invalides.
	 */
	@Test(expected = TriangleException.class)
	public void notATriangle3() throws TriangleException {
		new Triangle(2, 8, 1);
	}

	/**
	 * Test de la création d'un triangle avec un côté nul.
	 */
	@Test(expected = TriangleException.class)
	public void zeroSide1() throws TriangleException {
		new Triangle(0, 3, 4);
	}

	/**
	 * Test de la création d'un triangle avec un côté nul.
	 */
	@Test(expected = TriangleException.class)
	public void zeroSide2() throws TriangleException {
		new Triangle(4, 0, 3);
	}

	/**
	 * Test de la création d'un triangle avec un côté nul.
	 */
	@Test(expected = TriangleException.class)
	public void zeroSide3() throws TriangleException {
		new Triangle(3, 4, 0);
	}

	/**
	 * Test de la création d'un triangle avec tous les côtés nuls (un seul
	 * point).
	 */
	@Test(expected = TriangleException.class)
	public void onePoint() throws TriangleException {
		new Triangle(0, 0, 0);
	}

	/**
	 * Test de la création d'un triangle avec un côté négatif.
	 */
	@Test(expected = TriangleException.class)
	public void negativeSide1() throws TriangleException {
		new Triangle(-3, 3, 5);
	}

	/**
	 * Test de la création d'un triangle avec un côté négatif.
	 */
	@Test(expected = TriangleException.class)
	public void negativeSide2() throws TriangleException {
		new Triangle(5, -3, 3);
	}

	/**
	 * Test de la création d'un triangle avec un côté négatif.
	 */
	@Test(expected = TriangleException.class)
	public void negativeSide3() throws TriangleException {
		new Triangle(3, 5, -3);
	}

	/**
	 * Test de la création d'un triangle avec quatre valeurs.
	 */
	@Test(expected = TriangleException.class)
	public void tooManyValues() throws TriangleException {
		new Triangle(new double[] { 2, 4, 5, 8 });
	}

	/**
	 * Test de la création d'un triangle avec 2 valeurs.
	 */
	@Test(expected = TriangleException.class)
	public void notEnoughValues() throws TriangleException {
		new Triangle(new double[] { 2, 4 });
	}

	/**
	 * Test de la méthode getType() sur un triangle scalène.
	 */
	@Test
	public void scaleneTriangle() throws TriangleException {
		Triangle t = new Triangle(6, 5, 7);
		assertEquals(Type.SCALENE, t.getType());
		assertFalse(t.isIsosceles());
		assertFalse(t.isEquilateral());
	}

	/**
	 * Test de la méthode getType() sur un triangle isocèle.
	 */
	@Test
	public void isoscelesTriangle() throws TriangleException {
		double[] values = { 6, 1, 6 };
		for (int i = 0; i < 3; i++) {
			Triangle t = new Triangle(values);
			assertEquals(Type.ISOSCELES, t.getType());
			assertTrue(t.isIsosceles());
			assertFalse(t.isEquilateral());
			double first = values[0];
			for (int j = 0; j < values.length - 1; j++) {
				values[j] = values[j + 1];
			}
			values[values.length - 1] = first;
		}
	}

	/**
	 * Test de la méthode getType() sur un triangle équilatéral.
	 */
	@Test
	public void equilateralTriangle() throws TriangleException {
		Triangle t = new Triangle(4, 4, 4);
		assertEquals(Type.EQUILATERAL, t.getType());
		assertTrue(t.isIsosceles());
		assertTrue(t.isEquilateral());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle scalène dont le plus
	 * grand angle est aigu.
	 */
	@Test
	public void scaleneTriangleAcute() throws TriangleException {
		assertEquals(Angle.ACUTE, new Triangle(6, 5, 7).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle isocèle dont le plus
	 * grand angle est aigu.
	 */
	@Test
	public void isoscelesTriangleAcute() throws TriangleException {
		assertEquals(Angle.ACUTE, new Triangle(6, 1, 6).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle équilatéral dont le
	 * plus grand angle est aigu.
	 */
	@Test
	public void equilateralTriangleAcute() throws TriangleException {
		assertEquals(Angle.ACUTE, new Triangle(4, 4, 4).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle scalène dont le plus
	 * grand angle est obtus.
	 */
	@Test
	public void scaleneTriangleObtuse() throws TriangleException {
		assertEquals(Angle.OBTUSE, new Triangle(5, 6, 10).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle isocèle dont le plus
	 * grand angle est obtus.
	 */
	@Test
	public void isoscelesTriangleObtuse() throws TriangleException {
		assertEquals(Angle.OBTUSE, new Triangle(7, 4, 4).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle scalène dont le plus
	 * grand angle est droit.
	 */
	@Test
	public void scaleneTriangleRight() throws TriangleException {
		assertEquals(Angle.RIGHT, new Triangle(3, 4, 5).getBiggerAngle());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle isocèle dont le plus
	 * grand angle est droit.
	 */
	@Test
	public void isoscelesTriangleRight() throws TriangleException {
		assertEquals(Angle.RIGHT,
				new Triangle(Math.sqrt(2), 2, Math.sqrt(2)).getBiggerAngle());
	}

	/**
	 * Test de la méthode getType() sur un très petit triangle équilatéral.
	 */
	@Test
	public void verySmallTriangle() throws TriangleException {
		Triangle t = new Triangle(0.001, 0.001, 0.001);
		assertEquals(Type.EQUILATERAL, t.getType());
		assertTrue(t.isIsosceles());
		assertTrue(t.isEquilateral());
	}

	/**
	 * Test de la méthode getType() sur un très grand triangle équilatéral.
	 */
	@Test
	public void veryBigTriangle() throws TriangleException {
		Triangle t = new Triangle(88888, 88888, 88888);
		assertEquals(Type.EQUILATERAL, t.getType());
		assertTrue(t.isIsosceles());
		assertTrue(t.isEquilateral());
	}

	/**
	 * Test de la méthode getType() sur un triangle presque isocèle.
	 */
	@Test
	public void almostIsoscelesTriangle() throws TriangleException {
		Triangle t = new Triangle(2.99999, 3, 5);
		assertEquals(Type.SCALENE, t.getType());
		assertFalse(t.isIsosceles());
		assertFalse(t.isEquilateral());
	}

	/**
	 * Test de la méthode getType() sur un triangle presque équilatéral.
	 */
	@Test
	public void almostEquilateralTriangle() throws TriangleException {
		Triangle t = new Triangle(3.00001, 3, 3);
		assertEquals(Type.ISOSCELES, t.getType());
		assertTrue(t.isIsosceles());
		assertFalse(t.isEquilateral());
	}

	/**
	 * Test de la méthode getBiggerAngle() sur un triangle presque droit.
	 */
	@Test
	public void scaleneTriangleAlmostRight() throws TriangleException {
		Triangle t = new Triangle(3, 4, 5.00001);
		assertEquals(Angle.OBTUSE, t.getBiggerAngle());
	}

	/**
	 * Test de la méthode toString().
	 */
	@Test
	public void print() throws TriangleException {
		assertEquals("triangle " + Type.valueOf(Type.SCALENE.toString()),
				new Triangle(10, 5, 7).toString());
	}

}
