package ch.epfl.isochrone.timetable;

import static org.junit.Assert.assertEquals;

import java.util.Collections;

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

import ch.epfl.isochrone.geo.PointWGS84;

public class TestGraphEdge {
    // 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() {
        int i1 = GraphEdge.packTrip(0, 0);
        i1 = GraphEdge.unpackTripDepartureTime(0);
        i1 = GraphEdge.unpackTripDuration(0);
        i1 = GraphEdge.unpackTripArrivalTime(0) + i1;
        Stop s = null;
        GraphEdge e = new GraphEdge(s, 0, Collections.<Integer> emptySet());
        s = e.destination();
        i1 = e.earliestArrivalTime(0);

        GraphEdge.Builder b = new GraphEdge.Builder(s);
        b.setWalkingTime(0);
        b.addTrip(0, 0);
        e = b.build();
    }

    @Test(expected = IllegalArgumentException.class)
    public void tooSmallDepartureTime() {
        GraphEdge.packTrip(-10, 100);
    }

    @Test(expected = IllegalArgumentException.class)
    public void tooBigDepartureTime() {
        GraphEdge.packTrip(108000, 108001);
    }

    @Test(expected = IllegalArgumentException.class)
    public void tooSmallDurationTime() {
        GraphEdge.packTrip(102, 100);
    }

    @Test(expected = IllegalArgumentException.class)
    public void tooBigDurationTime() {
        GraphEdge.packTrip(1, 10001);
    }

    @Test
    public void unpackIsOk() {
        int a;
        int b;

        for (int i = 0; i < 1000; i++) {
            a = (int) (Math.random() * 999);
            b = (int) (Math.random() * 99);

            assertEquals(
                    GraphEdge.unpackTripDepartureTime(GraphEdge.packTrip(a, a
                            + b)), a);
            assertEquals(GraphEdge.unpackTripArrivalTime(GraphEdge.packTrip(a,
                    a + b)), a + b);
            assertEquals(
                    GraphEdge.unpackTripDuration(GraphEdge.packTrip(a, a + b)),
                    b);
        }
    }

    @Test
    public void earliestArrivalTimeIsOk() {
        Stop s = new Stop("Arret", new PointWGS84(0.5, 0.5));
        GraphEdge.Builder b1 = new GraphEdge.Builder(s);
        b1.setWalkingTime(SecondsPastMidnight.fromHMS(0, 10, 0)).addTrip(
                SecondsPastMidnight.fromHMS(0, 10, 0),
                SecondsPastMidnight.fromHMS(0, 15, 0));

        GraphEdge g1 = b1.build();

        assertEquals(
                g1.earliestArrivalTime(SecondsPastMidnight.fromHMS(0, 10, 0)),
                SecondsPastMidnight.fromHMS(0, 15, 0));
        assertEquals(
                g1.earliestArrivalTime(SecondsPastMidnight.fromHMS(0, 9, 0)),
                SecondsPastMidnight.fromHMS(0, 15, 0));
        assertEquals(
                g1.earliestArrivalTime(SecondsPastMidnight.fromHMS(0, 0, 0)),
                SecondsPastMidnight.fromHMS(0, 10, 0));

        GraphEdge.Builder b2 = new GraphEdge.Builder(s);
        b2.addTrip(SecondsPastMidnight.fromHMS(10, 10, 0),
                SecondsPastMidnight.fromHMS(10, 20, 0)).addTrip(
                SecondsPastMidnight.fromHMS(10, 40, 0),
                SecondsPastMidnight.fromHMS(10, 50, 0));

        GraphEdge g2 = b2.build();

        assertEquals(
                g2.earliestArrivalTime(SecondsPastMidnight.fromHMS(10, 0, 0)),
                SecondsPastMidnight.fromHMS(10, 20, 0));
        assertEquals(
                g2.earliestArrivalTime(SecondsPastMidnight.fromHMS(10, 10, 0)),
                SecondsPastMidnight.fromHMS(10, 20, 0));
        assertEquals(
                g2.earliestArrivalTime(SecondsPastMidnight.fromHMS(10, 10, 10)),
                SecondsPastMidnight.fromHMS(10, 50, 0));
        assertEquals(
                g2.earliestArrivalTime(SecondsPastMidnight.fromHMS(11, 0, 10)),
                SecondsPastMidnight.INFINITE);

        GraphEdge.Builder b3 = new GraphEdge.Builder(s);

        int a = (int) (Math.random() * 59);
        int b = (int) (Math.random() * 59);
        int c = (int) (Math.random() * 600);

        for (int i = 5; i < 23; i++) {
            b3.addTrip(SecondsPastMidnight.fromHMS(i, a, b),
                    SecondsPastMidnight.fromHMS(i, a, b) + c);
        }
        GraphEdge g3 = b3.build();

        assertEquals(
                g3.earliestArrivalTime(SecondsPastMidnight.fromHMS(1, 0, 0)),
                SecondsPastMidnight.fromHMS(5, a, b) + c);
        assertEquals(
                g3.earliestArrivalTime(SecondsPastMidnight.fromHMS(6, 0, 0)),
                SecondsPastMidnight.fromHMS(6, a, b) + c);
        assertEquals(
                g3.earliestArrivalTime(SecondsPastMidnight.fromHMS(23, 0, 0)),
                SecondsPastMidnight.INFINITE);
    }
}
