/**
 * 
 */
package anoncard;

import static org.junit.Assert.*;

import mixconfig.tools.dataretention.smartcard.ApduConstants;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import anoncard.util.Helpers;
import anoncard.util.ISOExceptionException;
import anoncard.util.ResponseException;

/**
 * @author christoph
 * 
 */
public class DateTest {

	private Date date;
	private byte[] dateBytes;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		date = new Date();
		dateBytes = new byte[] { 27, 01, 20, 10 };
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	/**
	 * Test method for {@link anoncard.Date#getDay()},
	 * {@link anoncard.Date#setDate()} and
	 * {@link anoncard.Date#checkInitialisationAndThrowException()}.
	 */
	@Test
	public void testGetDay() {
		try {
			date.getDay();
			fail("Expect Exception from unset date");
		} catch (ISOExceptionException e) {
			if (!Helpers.checkErrorCodeInException(e, ApduConstants.EXCEPTION_DATE_NOT_SET)) {
				fail(Helpers.alertResponseMismatch(e, ApduConstants.EXCEPTION_DATE_NOT_SET));
			}
		} catch (ResponseException e) {
			fail("Got normal response: " + e.getResponse());
		}
		date.setDate(dateBytes);
		assertEquals(dateBytes[0], date.getDay());
	}

	/**
	 * Test method for {@link anoncard.Date#getMonth()},
	 * {@link anoncard.Date#setDate()} and
	 * {@link anoncard.Date#checkInitialisationAndThrowException()}.
	 */
	@Test
	public void testGetMonth() {
		try {
			date.getMonth();
			fail("Expect Exception from unset date");
		} catch (ISOExceptionException e) {
			if (!Helpers.checkErrorCodeInException(e, ApduConstants.EXCEPTION_DATE_NOT_SET)) {
				fail(Helpers.alertResponseMismatch(e, ApduConstants.EXCEPTION_DATE_NOT_SET));
			}
		} catch (ResponseException e) {
			fail("Got normal response: " + e.getResponse());
		}
		date.setDate(dateBytes);
		assertEquals(dateBytes[1], date.getMonth());
	}

	/**
	 * Test method for {@link anoncard.Date#getYear()} and and
	 * {@link anoncard.Date#checkInitialisationAndThrowException()}.
	 */
	@Test
	public void testGetYearSetYear() {
		try {
			date.getYear();
			fail("Expect Exception from unset date");
		} catch (ISOExceptionException e) {
			if (!Helpers.checkErrorCodeInException(e, ApduConstants.EXCEPTION_DATE_NOT_SET)) {
				fail(Helpers.alertResponseMismatch(e, ApduConstants.EXCEPTION_DATE_NOT_SET));
			}
		} catch (ResponseException e) {
			fail("Got normal response: " + e.getResponse());
		}
		date.setDay((byte) 1);
		date.setMonth((byte) 1);
		date.setYear(dateBytes, (short) 2);
		assertArrayEquals(new byte[] { dateBytes[2], dateBytes[3] }, date.getYear());
		date.setYear(dateBytes, (short) 3);
		assertArrayEquals(new byte[] { dateBytes[2], dateBytes[3] }, date.getYear());
	}

	/**
	 * Test method for {@link anoncard.Date#getDate()} and
	 * {@link anoncard.Date#setDate()}.
	 */
	@Test
	public void testGetDateSetDate() {
		try {
			date.getDate();
			fail("Expect Exception from unset date");
		} catch (ISOExceptionException e) {
			if (!Helpers.checkErrorCodeInException(e, ApduConstants.EXCEPTION_DATE_NOT_SET)) {
				fail(Helpers.alertResponseMismatch(e, ApduConstants.EXCEPTION_DATE_NOT_SET));
			}
		} catch (ResponseException e) {
			fail("Got normal response: " + e.getResponse());
		}
		date.setDate(dateBytes);
		assertArrayEquals(dateBytes, date.getDate());
		date.setDate(dateBytes, (short) 1);
		assertArrayEquals(dateBytes, date.getDate());
		date.setDate(new byte[] { 0, 1, 2, 3, 4, 5, 6 }, (short) 1);
		assertArrayEquals(new byte[] { 1, 2, 3, 4 }, date.getDate());
		date.setDate(new byte[] { 0, 1, 2, 3, 4, 5, 6 }, (short) 3);
		assertArrayEquals(new byte[] { 3, 4, 5, 6 }, date.getDate());
	}

	/**
	 * Test method for {@link anoncard.Date#reset()} and
	 * {@link anoncard.Date#isSet()}.
	 */
	@Test
	public void testResetIsSet() {
		assertFalse(date.isSet());
		date.setDate(dateBytes);
		assertTrue(date.isSet());
		date.reset();
		assertFalse(date.isSet());
	}

	/**
	 * Test method for {@link anoncard.Date#isNotOutdated(byte, byte[], short)}.
	 */
	@Test
	public void testIsNotOutdated() {
		byte[] today = new byte[] { 27, 12, 20, 10 };
		byte[] past = new byte[] { 27, 6, 20, 10 };
		date.setDate(today);

		for (byte i = 0; i <= 5; i++) {
			assertFalse(i + " months are still not ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}
		for (byte i = 6; i <= 13; i++) {
			assertTrue(i + " months are already ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}

		today = new byte[] { 27, 12, 19, 99 };
		past = new byte[] { 26, 6, 19, 99 };
		date.setDate(today);
		for (byte i = 0; i <= 6; i++) {
			assertFalse(i + " months are still not ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}
		for (byte i = 7; i <= 13; i++) {
			assertTrue(i + " months are already ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}
		today = new byte[] { 27, 12, 19, 99 };
		past = new byte[] { 26, 6, 19, 98 };
		date.setDate(today);
		for (byte i = 0; i <= 18; i++) {
			assertFalse(i + " months are still not ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}
		for (byte i = 19; i <= 25; i++) {
			assertTrue(i + " months are already ok\n today: " + byteDatesToString(today) + "\n past: " + byteDatesToString(past), date.isNotOutdated(i, past, (short) 0));
		}

		assertFalse(date.isNotOutdated((byte) 12, new byte[] { 0, 1, 2, 3, 4, 5, 6 }, (short) 4));
		assertFalse(date.isNotOutdated((byte) -12, new byte[] { 0, 1, 2, 3, 4, 5, 6 }, (short) 0));

	}

	private String byteDatesToString(byte[] date) {
		return (date[0] < 10 ? "0" + date[0] : date[0]) + "." + (date[1] < 10 ? "0" + date[1] : date[1]) + "." + date[2] + (date[3] < 10 ? "0" + date[3] : date[3]);
	}

}
