package ch.epfl.isochrone.timetable;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.junit.Ignore;
import org.junit.Test;

import ch.epfl.isochrone.timetable.Date.DayOfWeek;
import ch.epfl.isochrone.timetable.Date.Month;
import static org.junit.Assert.assertTrue;

public class TestService {
    // Le "test" suivant n'en est pas un à proprement parler, raison pour
    // laquelle il est ignoré (annotation @Ignore). Son seul but est de garantir
    // que les noms des classes et méthodes sont corrects.
    @Test
    @Ignore
    public void namesAreOk() {
        Date d = new Date(1, Month.JANUARY, 2000);
        Service s = new Service("s", d, d,
                Collections.<Date.DayOfWeek> emptySet(),
                Collections.<Date> emptySet(), Collections.<Date> emptySet());
        s.name();
        s.isOperatingOn(d);

        Service.Builder sb = new Service.Builder("s", d, d);
        sb.name();
        sb.addOperatingDay(DayOfWeek.MONDAY);
        sb.addExcludedDate(d);
        sb.addIncludedDate(d);
        sb.build();
    }

    @Test(expected = java.lang.IllegalArgumentException.class)
    public void tooEarlyIncludedDate() {
        Date d1 = new Date(10, Month.JANUARY, 2000);
        Date d2 = new Date(17, Month.FEBRUARY, 2001);
        Date d3 = new Date(1, Month.JANUARY, 2000);

        Service.Builder sb = new Service.Builder("s", d1, d2);

        sb.addIncludedDate(d3);
    }

    @Test(expected = java.lang.IllegalArgumentException.class)
    public void tooLateIncludedDate() {
        Date d1 = new Date(10, Month.JANUARY, 2000);
        Date d2 = new Date(17, Month.FEBRUARY, 2001);
        Date d3 = new Date(1, Month.JANUARY, 2002);

        Service.Builder sb = new Service.Builder("s", d1, d2);

        sb.addIncludedDate(d3);
    }

    @Test(expected = java.lang.IllegalArgumentException.class)
    public void tooEarlyExcludedDate() {
        Date d1 = new Date(10, Month.JANUARY, 2000);
        Date d2 = new Date(17, Month.FEBRUARY, 2001);
        Date d3 = new Date(1, Month.JANUARY, 2000);

        Service.Builder sb = new Service.Builder("s", d1, d2);

        sb.addExcludedDate(d3);
    }

    @Test(expected = java.lang.IllegalArgumentException.class)
    public void tooLateExcludedDate() {
        Date d1 = new Date(10, Month.JANUARY, 2000);
        Date d2 = new Date(17, Month.FEBRUARY, 2001);
        Date d3 = new Date(1, Month.JANUARY, 2002);

        Service.Builder sb = new Service.Builder("s", d1, d2);

        sb.addExcludedDate(d3);
    }

    @Test
    public void normalDate() {
        Date d1;
        Date d2;
        Date d3;
        Date d4;
        Date d5;

        boolean d3Diffd4;

        Service.Builder sb;
        Service s;
        Date.DayOfWeek dw;

        Month[] tabMonth = Month.values();

        for (int i = 0; i < 1000; i++) {
            int a = (int) Math.random() * 9999;
            int b = (int) Math.random() * 9999;
            int c = (int) Math.random() * 9999;
            int d = (int) Math.random() * 9999;

            d1 = new Date(a % 28 + 1, tabMonth[a % 12], 2000 + a % 10);
            d2 = new Date(b % 28 + 1, tabMonth[b % 12], 2020 + b % 10);
            d3 = new Date(c % 28 + 1, tabMonth[c % 12], 2010 + c % 10);
            d4 = new Date(d % 28 + 1, tabMonth[d % 12], 2010 + d % 10);

            sb = new Service.Builder("a", d1, d2);

            sb.addExcludedDate(d3);

            if (d3.compareTo(d4) != 0) {
                sb.addIncludedDate(d4);
                d3Diffd4 = true;

            } else {
                d3Diffd4 = false;
            }

            dw = d3.dayOfWeek();
            sb.addOperatingDay(dw);

            s = sb.build();

            if (d3Diffd4) {
                assertTrue(s.isOperatingOn(d4));
            }
            assertTrue(!s.isOperatingOn(d3));

            d5 = new Date(3 + dw.ordinal(), 3, 2014);
            if (d5.compareTo(d3) != 0) {
                assertTrue(s.isOperatingOn(d5));
            }

        }
    }

    @Test
    public void immua() {
        Set<Date> excludedDates = new HashSet<Date>();
        Set<Date.DayOfWeek> dayOfWeek = new HashSet<Date.DayOfWeek>();

        Date today = new Date(3, 3, 2014);
        excludedDates.add(today);
        dayOfWeek.add(Date.DayOfWeek.MONDAY);

        Service s = new Service("s", new Date(20, 2, 2014), new Date(20, 3,
                2014), dayOfWeek, excludedDates, Collections.<Date> emptySet());

        excludedDates.remove(today);

        assertTrue(!s.isOperatingOn(today));
    }
}
