package de.duehl.basics.datetime.date;

/*
 * Copyright 2018 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import static de.duehl.basics.datetime.date.DateCalculations.*;

public class DateCalculationsTest {

    @Test
    public void parseDateWrongString() {
        ImmutualDate date = parseDate("foo");

        assertEquals(0, date.getDay()  );
        assertEquals(0, date.getMonth());
        assertEquals(0, date.getYear() );

        assertFalse(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWord() {
        ImmutualDate date = parseDate("11. Februar 1967");

        assertEquals(11,   date.getDay()  );
        assertEquals(2,    date.getMonth());
        assertEquals(1967, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateNormalDate() {
        ImmutualDate date = parseDate("11.02.1967");

        assertEquals(11, date.getDay());
        assertEquals(2, date.getMonth());
        assertEquals(1967, date.getYear());

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateUnixDate() {
        ImmutualDate date = parseDate("Wed Jan 18 12:01:50 CET 2012");
        // dow mon dd hh:mm:ss zzz yyyy

        assertEquals(18,   date.getDay()  );
        assertEquals(1,    date.getMonth());
        assertEquals(2012, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordWrongSpelledMonth() {
        ImmutualDate date = new ImmutualDate("11. Dronember 1967");

        assertEquals(11,   date.getDay()  );
        assertEquals(0,    date.getMonth());
        assertEquals(1967, date.getYear() );

        assertFalse(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordLastCentury() {
        ImmutualDate date = new ImmutualDate("29. März 1999");

        assertEquals(29,   date.getDay()  );
        assertEquals(3,    date.getMonth());
        assertEquals(1999, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordWithDot() {
        ImmutualDate date = new ImmutualDate("29. März. 1999");

        assertEquals(29,   date.getDay()  );
        assertEquals(3,    date.getMonth());
        assertEquals(1999, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordYearTwoDigit() {
        ImmutualDate date = parseDate("31. Dez. 16");

        assertEquals(31,   date.getDay()  );
        assertEquals(12,    date.getMonth());
        assertEquals(2016, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordShortenedHyphenYearTwoDigit() {
        ImmutualDate date = parseDate("31-Okt.-16");

        assertEquals(31,   date.getDay()  );
        assertEquals(10,    date.getMonth());
        assertEquals(2016, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordHyphenYearTwoDigitWithoutPoint() {
        ImmutualDate date = parseDate("31-Okt-16");

        assertEquals(31,   date.getDay()  );
        assertEquals(10,    date.getMonth());
        assertEquals(2016, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordHyphenYearTwoDigit() {
        ImmutualDate date = parseDate("31-Oktober-16");

        assertEquals(31,   date.getDay()  );
        assertEquals(10,    date.getMonth());
        assertEquals(2016, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void parseDateMonthAsLongWordHyphen() {
        ImmutualDate date = parseDate("31-Oktober-2016");

        assertEquals(31,   date.getDay()  );
        assertEquals(10,    date.getMonth());
        assertEquals(2016, date.getYear() );

        assertTrue(date.isValid());
    }

    @Test
    public void leapYear001() {
        assertFalse(isLeapYear(1899));
    }

    @Test
    public void leapYear002() {
        assertFalse(isLeapYear(1900));
    }

    @Test
    public void leapYear003() {
        assertTrue(isLeapYear(1904));
    }

    @Test
    public void leapYear004() {
        assertTrue(isLeapYear(1908));
    }

    @Test
    public void leapYear005() {
        assertTrue(isLeapYear(1996));
    }

    @Test
    public void leapYear006() {
        assertTrue(isLeapYear(2000));
    }

    @Test
    public void leapYear007() {
        assertFalse(isLeapYear(2001));
    }

    @Test
    public void leapYear008() {
        assertTrue(isLeapYear(2012));
    }

    @Test
    public void mupltipleEasterDaysValid() {
        /* Berechnet alle Ostersonntage von 1895 bis 2020, prüft diese, ob sie
         * valide sind.
         */
        for (int year=1895; year<=2020; ++year) {
            ImmutualDate date = calculateEasterSunday(year);
            assertTrue(date.isValid());
        }
    }

    @Test
    public void mupltipleEasterDaysisSunday() {
        /* Berechnet alle Ostersonntage von 1895 bis 2020, prüft diese, ob sie
         * Sonntage sind.
         */
        for (int year=1895; year<=2020; ++year) {
            ImmutualDate date = calculateEasterSunday(year);
            assertEquals(Weekday.SUNDAY, date.dayOfTheWeek());
        }
    }

    @Test
    public void easterDay01() {
        ImmutualDate date = calculateEasterSunday(2012);

        assertEquals(8,    date.getDay()  );
        assertEquals(4,    date.getMonth());
        assertEquals(2012, date.getYear() );
    }

    // ... TODO more tests easterDay...

    @Test
    public void dayOfTheWeek001() {
        Weekday weekday = dayOfTheWeek(14, 7, 1789); // Erstürmung der Bastille

        assertEquals(Weekday.TUESDAY, weekday);
    }

    @Test
    public void dayOfTheWeek002() {
        Weekday weekday = dayOfTheWeek(23, 5, 1949); // Gründung der Bundesrepublik

        assertEquals(Weekday.MONDAY, weekday);
    }

    @Test
    public void dayOfTheWeek003() {
        Weekday weekday = dayOfTheWeek(18, 1, 1892); // * Oliver Hardy

        assertEquals(Weekday.MONDAY, weekday);
    }

    @Test
    public void dayOfTheWeek004() {
        Weekday weekday = dayOfTheWeek(9, 11, 1989); // Mauerfall

        assertEquals(Weekday.THURSDAY, weekday);
    }

    @Test
    public void dayOfTheWeek005() {
        Weekday weekday = dayOfTheWeek(24, 4, 1982); // ?

        assertEquals(Weekday.SATURDAY, weekday);
    }

    @Test
    public void dayOfTheWeek006() {
        Weekday weekday = dayOfTheWeek(18, 9, 1783); // ?

        assertEquals(Weekday.THURSDAY, weekday);
    }

    @Test
    public void dayOfTheWeek007() {
        Weekday weekday = dayOfTheWeek(1, 1, 2000); // ?

        assertEquals(Weekday.SATURDAY, weekday);
    }

    @Test
    public void dayOfTheWeek008() {
        Weekday weekday = dayOfTheWeek(19, 6, 2054); // ?

        assertEquals(Weekday.FRIDAY, weekday);
    }

    @Test
    public void dayOfTheWeek009() {
        Weekday weekday = dayOfTheWeek(5, 1, 2012); // war mal heute

        assertEquals(Weekday.THURSDAY, weekday);
    }

    @Test
    public void dayOfTheWeek010() {
        Weekday weekday = dayOfTheWeek(20, 12, 2012); // 70. Geb. Gerd

        assertEquals(Weekday.THURSDAY, weekday);
    }

}
