package edu.wlu.cs.sprenkle.tests;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import edu.wlu.cs.sprenkle.Birthday;

/**
 * Tests the Birthday class
 * 
 * @author Sara Sprenkle
 *
 */
class BirthdayTest {

    private Birthday newYearsBirthday;
    private Birthday endOfJuneBirthday;
    private Birthday aBirthday;
    
    @BeforeEach
    void setUp() throws Exception {
	newYearsBirthday = new Birthday(1, 1);
	endOfJuneBirthday = new Birthday(6, 30);
    }
    
    @Test
    final void testBirthdayConstructor() {
	assertEquals(1, newYearsBirthday.getMonth());
	assertEquals(1, newYearsBirthday.getDay());

	assertEquals(6, endOfJuneBirthday.getMonth());
	assertEquals(30, endOfJuneBirthday.getDay());
	
	// confirm no problem with a leap year birthday:
	assertDoesNotThrow(() -> {
		Birthday leapYearBirthday = new Birthday(2, 29);
	    });

    }

    @Test
    final void testBadConstructorUse() {
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(0, 1);
	    });
	
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(1, 0);
	    });
	
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(12, 32);
	    });
	
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(2, -1);
	    });
	
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(4, 31);
	    });
	
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday = new Birthday(2, 30);
	    });
    }

    @Test
    final void testToString() {
	String nydayString = "1/1";
	String juneString = "6/30";
	
	assertEquals(nydayString, newYearsBirthday.toString());
	assertEquals(juneString, endOfJuneBirthday.toString());
    }
    
    @Test
    final void testLongStringFormat() {
	String nydayString = "January 1";
	String juneString = "June 30";
	
	assertEquals(nydayString, newYearsBirthday.longStringFormat());
	assertEquals(juneString, endOfJuneBirthday.longStringFormat());
    }
    
    @Test
    final void testSetBirthday() {
	newYearsBirthday.setBirthday(1, 2);
	assertEquals(1, newYearsBirthday.getMonth());
	assertEquals(2, newYearsBirthday.getDay());
    }
    
    @Test
    final void testGetDay() {
	assertEquals(1, newYearsBirthday.getDay());
	assertEquals(30, endOfJuneBirthday.getDay());
    }
    
    @Test
    final void testGetMonth() {
	assertEquals(1, newYearsBirthday.getMonth());
	assertEquals(6, endOfJuneBirthday.getMonth());
    }
    
    @Test
    final void testCompareTo() {
	assertEquals(-1, newYearsBirthday.compareTo(endOfJuneBirthday));
	assertEquals(1, endOfJuneBirthday.compareTo(newYearsBirthday));
	
	Birthday sameMonth = new Birthday(6, 27);
	
	assertEquals(-3, sameMonth.compareTo(endOfJuneBirthday));
	assertEquals(3, endOfJuneBirthday.compareTo(sameMonth));
	
	Birthday sameDay = new Birthday(1, 1);
	assertEquals(0, sameDay.compareTo(newYearsBirthday));
	assertEquals(0, newYearsBirthday.compareTo(sameDay));
    }

    @Test
    final void testEquals() {
	assertFalse(newYearsBirthday.equals(endOfJuneBirthday));
	assertFalse(endOfJuneBirthday.equals(newYearsBirthday));
	
	Birthday sameMonth = new Birthday(6, 27);
	
	assertFalse(sameMonth.equals(endOfJuneBirthday));
	assertFalse(endOfJuneBirthday.equals(sameMonth));
	
	Birthday sameDay = new Birthday(1, 1);
	assertTrue(sameDay.equals(newYearsBirthday));
	assertTrue(newYearsBirthday.equals(sameDay));
    }
    
    @Test
    final void testThrownExceptions() {
	aBirthday = new Birthday(1, 1);
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(0, 1);
	    });
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(1, 0);
	    });
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(12, -1);
	    });
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(6, 31);
	    });
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(10, 32);
	    });
	assertThrows(IllegalArgumentException.class, () -> {
		aBirthday.setBirthday(-1, 1);
	    });
    }

}
