import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class RationalTest {

	Rational zero, one, five;
	Rational rop1, rop2, rop3, rop4, rop5;

	@Before
	public void setUp() throws Exception {
		zero = new Rational();
		one = new Rational(1);
		five = new Rational(5);
		rop1 = new Rational(32, 81);
		rop2 = new Rational(45, 72);
		rop3 = new Rational((long)Math.pow(2, 60), 147);
		rop4 = new Rational(63, (long)Math.pow(2, 59));
		rop5 = new Rational((long)Math.pow(2, 59), 63);
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testRational() {
		zero = new Rational();
		assertEquals(0, zero.numerator());
		assertEquals(1, zero.denominator());
	}

	@Test
	public void testRationalIntInt() {
		Rational anotherZero = new Rational(0, 5);
		assertEquals(0, anotherZero.numerator());
		assertEquals(1, anotherZero.denominator());

		Rational r1 = new Rational(2, 10);
		assertEquals(1, r1.numerator());
		assertEquals(5, r1.denominator());
		
		Rational r2 = new Rational(2, -10);
		assertEquals(-1, r2.numerator());
		assertEquals(5, r2.denominator());
		
		Rational r3 = new Rational(-2, 10);
		assertEquals(-1, r3.numerator());
		assertEquals(5, r3.denominator());
		
		Rational r4 = new Rational(-2, -10);
		assertEquals(1, r4.numerator());
		assertEquals(5, r4.denominator());
		
		Rational r5 = new Rational(0, -10);
		assertEquals(0, r5.numerator());
		assertEquals(1, r5.denominator());
	}

	@Test
	public void testRationalRational() {
		Rational r1 = new Rational(3, 5);
		Rational r2 = new Rational(r1);
		assertEquals(r1.numerator(), r2.numerator());
		assertEquals(r1.denominator(), r2.denominator());
	}

	@Test
	public void testRationalInt() {
		assertEquals(1, one.numerator());
		assertEquals(1, one.denominator());
//		Rational five = new Rational(5);
		assertEquals(5, five.numerator());
		assertEquals(1, five.denominator());
	}

	@Test
	public void testAdd() {
		Rational six = five.add(one);
		assertEquals(6, six.numerator());
		assertEquals(1, six.denominator());
		six = one.add(five);
		assertEquals(6, six.numerator());
		assertEquals(1, six.denominator());
		Rational expected = new Rational(661, 648);
		Rational result = rop1.add(rop2);
		assertEquals(expected.numerator(), result.numerator());
		assertEquals(expected.denominator(), result.denominator());
	}

	@Test
	public void testSubtract() {
		Rational expected = new Rational(-149, 648);
		Rational result = rop1.subtract(rop2);
		assertEquals(expected.numerator(), result.numerator());
		assertEquals(expected.denominator(), result.denominator());

		result = rop1.subtract(rop1);
		assertEquals(zero.numerator(), result.numerator());
		assertEquals(zero.denominator(), result.denominator());
	}

	@Test
	public void testMultiply() {
		Rational expected = new Rational(6, 7);
		
		Rational result = rop3.multiply(rop4);
		assertEquals(expected.numerator(), result.numerator());
		assertEquals(expected.denominator(), result.denominator());
	}

	@Test
	public void testDivide() {
		Rational expected = new Rational(6, 7);
		Rational result = rop3.divide(rop5);
		assertEquals(expected.numerator(), result.numerator());
		assertEquals(expected.denominator(), result.denominator());
	}

	@Test
	public void testToString() {
		assertEquals("(1/5)", new Rational(1, 5).toString());
		assertEquals("(0/1)", zero.toString());
		assertEquals("(1/1)", one.toString());
		assertEquals("(5/1)", five.toString());
		assertEquals("(32/81)", rop1.toString());
	}

	@Test
	public void testCompareTo() {
		assertTrue(one.compareTo(zero) > 0);
		assertFalse(one.compareTo(zero) < 0);
		assertTrue(one.compareTo(five) < 0);
		assertFalse(one.compareTo(five) > 0);
		assertTrue(five.compareTo(one) > 0);
		assertFalse(five.compareTo(one) < 0);
		assertTrue(five.compareTo(five) == 0);
		assertTrue(rop1.compareTo(rop2) < 0);
		assertTrue(rop2.compareTo(rop1) > 0);
		assertTrue(rop3.compareTo(rop5) > 0);
		assertTrue(rop5.compareTo(rop3) < 0);
	}

}
