/*
 * Copyright 2011 Marc Grue.
 *
 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 * you may not use  this file  except in  compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed  under the  License is distributed on an "AS IS" BASIS,
 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 * implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.zest.sample.dcicargo.sample_a.context.shipping.booking;

import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import org.apache.zest.api.unitofwork.UnitOfWork;
import org.apache.zest.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
import org.apache.zest.sample.dcicargo.sample_a.data.entity.CargosEntity;
import org.apache.zest.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.location.Location;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType.*;

/**
 * Tests of the Build Delivery Snapshot subfunction use case.
 *
 * All deviations of the use case are tested one by one. The business rules are therefore enforcing the
 * structure for the test suite and not arbitrary ideas of the programmer what to test. If the business
 * analyst haven't foreseen a deviation in the use case, it's his responsibility that it's not tested.
 *
 * Test method names describe the test purpose. The prefix refers to the step in the use case.
 *
 * FIXME: Test methods call each other to allow ordered execution, ie. tests are not indepedants !
 */
public class BuildDeliverySnapshotTest
      extends TestApplication
{
    final Date TODAY = new Date();

    private Location HONGKONG;
    private Location STOCKHOLM;
    private Location NEWYORK;
    private Location DALLAS;
    private Location HANGZHOU;
    private Location HELSINKI;
    private Location TOKYO;
    private Location HAMBURG;
    private Voyage V100S;
    private Voyage V200T;
    private Voyage V300A;
    private Voyage V400S;
    private Voyage V500S;
    private Location SHANGHAI;
    private TrackingId trackingId;
    private Cargo cargo;
    private Itinerary itinerary;

    @Before
    public void prepareTest()
        throws Exception
    {
        super.prepareTest();
        UnitOfWork uow = module.currentUnitOfWork();
        HONGKONG = uow.get( Location.class, CNHKG.code().get() );
        STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
        SHANGHAI = uow.get( Location.class, CNSHA.code().get() );
        TOKYO = uow.get( Location.class, JNTKO.code().get() );
        NEWYORK = uow.get( Location.class, USNYC.code().get() );
        DALLAS = uow.get( Location.class, USDAL.code().get() );
        HANGZHOU = uow.get( Location.class, CNHGH.code().get() );
        HELSINKI = uow.get( Location.class, FIHEL.code().get() );
        HAMBURG = uow.get( Location.class, DEHAM.code().get() );
        V100S = uow.get( Voyage.class, "V100S" );
        V200T = uow.get( Voyage.class, "V200T" );
        V300A = uow.get( Voyage.class, "V300A" );
        V400S = uow.get( Voyage.class, "V400S" );
        V500S = uow.get( Voyage.class, "V500S" );

        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "ABC" );
        cargo = uow.get( Cargo.class, trackingId.id().get() );

        itinerary = itinerary(
            leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
            leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
            leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
        );


    }

    // DERIVE WITH ROUTE SPECIFICATION ==============================================================================

    @Test( expected = RouteException.class )
    public void deviation_2a_InvalidRouteSpecification_sameLocations() throws Exception
    {
        RouteSpecification routeSpec = routeSpecification( HONGKONG, HONGKONG, day( 20 ) );
        new BuildDeliverySnapshot( routeSpec ).get();
    }

    @Test( expected = RouteException.class )
    public void deviation_2b_InvalidRouteSpecification_tooEarlyDeadline() throws Exception
    {
        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, TODAY );
        new BuildDeliverySnapshot( routeSpec ).get();
    }

    @Test
    public void deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification() throws Exception
    {
        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
        Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();

        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
    }


    // DERIVE WITH NON-ROUTED CARGO ==============================================================================

    @Test
    public void deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo() throws Exception
    {
        deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification();

        UnitOfWork uow = module.currentUnitOfWork();
        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
        Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
        Cargo cargo = CARGOS.createCargo( routeSpec, delivery, "ABCD" );

        // Same as previous test (just build from cargo instead)
        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
    }


    // DERIVE WITH ROUTE SPECIFICATION + ITINERARY (Routed cargo) ==============================================

    @Test
    public void deviation_2d_UnsatisfyingItinerary_wrongOrigin() throws Exception
    {
        deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo();

        Itinerary itinerary = itinerary(
            leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
            leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
            leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
        );

        // Hangzhou not in itinerary first leg
        RouteSpecification routeSpec = routeSpecification( HANGZHOU, STOCKHOLM, day( 20 ) );
        cargo.itinerary().set( itinerary );
        cargo.routeSpecification().set( routeSpec );
        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();

        // Route specification not satisfied by itinerary
        assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
    }

    @Test
    public void deviation_2d_UnsatisfyingItinerary_wrongDestination() throws Exception
    {
        deviation_2d_UnsatisfyingItinerary_wrongOrigin();

        // Helsinki not in itinerary last leg
        RouteSpecification routeSpec = routeSpecification( HONGKONG, HELSINKI, day( 20 ) );
        cargo.routeSpecification().set( routeSpec );
        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();

        // Route specification not satisfied by itinerary
        assertThat( itinerary.lastLeg().unloadLocation().get(), is( not( equalTo( routeSpec.destination().get() ) ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
    }

    @Test
    public void deviation_2d_UnsatisfyingItinerary_missedDeadline() throws Exception
    {
        deviation_2d_UnsatisfyingItinerary_wrongDestination();

        // Arrival on day 12 according to itinerary is not meeting deadline
        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 14 ) );
        cargo.routeSpecification().set( routeSpec );
        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();

        // Route specification not satisfied by itinerary
        assertFalse( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
    }

    @Test
    public void deviation_3a_CargoHasNoHandlingHistory() throws Exception
    {
        deviation_2d_UnsatisfyingItinerary_missedDeadline();

        Date arrival = day( 16 );
        Date deadline = day( 20 );
        // Itinerary will satisfy route specification
        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, deadline );
        cargo.routeSpecification().set( routeSpec );
        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();

        // Route specification satisfied by itinerary
        assertThat( itinerary.firstLeg().loadLocation().get(), is( equalTo( routeSpec.origin().get() ) ) );
        assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
        assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );

        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
    }


    // DERIVE WITH ROUTE SPECIFICATION + ITINERARY + LAST HANDLING EVENT ============================================

    @Test
    public void deviation_4a_RECEIVE_1a_UnexpectedPort() throws Exception
    {
        deviation_3a_CargoHasNoHandlingHistory();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
        // Unexpected receipt in Shanghai
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, SHANGHAI, null );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        // We don't know what's next for a misdirected cargo
        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( SHANGHAI ) ) );

        // Cargo is still routed - but it should be re-routed according to new (unexpected) location.
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
    }

    @Test
    public void deviation_4a_RECEIVE_1b_ExpectedPort() throws Exception
    {
        deviation_4a_RECEIVE_1a_UnexpectedPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
        // Expected receipt in Hong Kong
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, HONGKONG, null );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );

        // We expect the cargo to be loaded on voyage V100S in Hong Kong
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
    }


    @Test
    public void deviation_4b_LOAD_2a_UnexpectedPort() throws Exception
    {
        deviation_4a_RECEIVE_1b_ExpectedPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
        // Unexpected load in Tokyo
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, TOKYO, V100S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
    }

    @Test
    public void deviation_4b_LOAD_2b_ExpectedPort() throws Exception
    {
        deviation_4b_LOAD_2a_UnexpectedPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
        // Expected load in Hong Kong
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V100S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );

        // We expect the cargo to be unloaded from voyage V100S in New York
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( NEWYORK ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
    }

    @Test
    public void deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary() throws Exception
    {
        deviation_4b_LOAD_2b_ExpectedPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
        // Load onto unexpected voyage
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V400S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( V400S ) ) );
    }

    @Test
    public void deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary() throws Exception
    {
        deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // The system doesn't currently check if handling events happen in the right order, so
        // a cargo can now suddenly load in New York, even though it hasn't got there yet.
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, LOAD, NEWYORK, V200T );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        // Should have been true, but we accept it for now...
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );

        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( NEWYORK ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( V200T ) ) );

        // We expect the cargo to be unloaded from voyage V200T in Dallas
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( DALLAS ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V200T ) ) );
    }


    @Test
    public void deviation_4c_UNLOAD_1a_UnexpectedPort() throws Exception
    {
        deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Unexpected unload in Tokyo
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, UNLOAD, TOKYO, V100S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
        cargo.delivery().set( delivery );

        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );

        // Cargo needs to be rerouted

        // Customer specifies a new route
        RouteSpecification routeSpec = routeSpecification( TOKYO, STOCKHOLM, day( 20 ) );
        cargo.routeSpecification().set( routeSpec );
        delivery = new BuildDeliverySnapshot( cargo ).get();
        cargo.delivery().set( delivery );

        // Old itinerary will not satisfy new route specification
        assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
        assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );

        // Old planned arrival time is still satisfying new deadline
        assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );

        // We don't know what's next before a new itinerary has been chosen
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        // Cargo is still misdirected (in unexpected location) according to old itinerary
        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );

        // Last known data
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );

        // New itinerary that satisfy the new route specification. New origin departure from Tokyo.
        Date arrival= day( 19 );
        itinerary = itinerary(
              leg( V400S, TOKYO, HAMBURG, day( 9 ), day( 16 ) ),
              leg( V500S, HAMBURG, STOCKHOLM, day( 17 ), arrival  )
        );

        // Customer reroutes cargo. This is a possible step in the cargo booking process.
        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
        delivery = cargo.delivery().get();

        // Cargo is on track again
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );

        // When a cargo is rerouted the (often misdirected) last handling event is flagged as disregarded
        // since it doesn't have to be part of the new itinerary (this isn't in the Citerus version).

        // We now expect the cargo to be loaded onto voyage V400S in Tokyo heading to Hamburg
        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( TOKYO ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V400S ) ) );

        // Cargo is not misdirected anymore according to new itinerary. Cargo location is now expected to be in Tokyo.
    }

    @Test
    public void deviation_4c_UNLOAD_1b_ExpectedMidpointLocation() throws Exception
    {
        deviation_4c_UNLOAD_1a_UnexpectedPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Unload at midpoint location of itinerary
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 8 ), day( 8 ), trackingId, UNLOAD, HAMBURG, V400S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HAMBURG ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );

        // We expect the cargo to be loaded onto voyage V200T in New York heading for Dallas
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HAMBURG ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V500S ) ) );
    }

    @Test
    public void deviation_4c_UNLOAD_1c_Destination() throws Exception
    {
        deviation_4c_UNLOAD_1b_ExpectedMidpointLocation();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Unload at destination
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, UNLOAD, STOCKHOLM, V500S );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );

        // Cargo has arrived at destination location
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );

        // We expect the cargo to be claimed by customer
        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( CLAIM ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( STOCKHOLM ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
    }


    @Test
    public void deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort() throws Exception
    {
        deviation_4c_UNLOAD_1c_Destination();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Cargo was handled by the customs authorities
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CUSTOMS, STOCKHOLM, null );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );

        // Cargo might be at destination, but the last handling event wasn't unloading
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );

        // Shouldn't we expect the cargo to be claimed by the customer now ?
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
    }


    @Test
    public void deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort() throws Exception
    {
        deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Cargo was claimed but not at destination location
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 16 ), trackingId, CLAIM, HELSINKI, null );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
        assertThat( delivery.eta().get(), is( equalTo( null ) ) );

        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HELSINKI ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );

        // Cargo is claimed but has not arrived yet in destination port
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
    }

    @Test
    public void deviation_4e_CLAIM_1b_CargoIsInDestinationPort() throws Exception
    {
        deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort();

        UnitOfWork uow = module.currentUnitOfWork();
        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );

        // Cargo was claimed by customer at destination location
        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CLAIM, STOCKHOLM, null );
        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();

        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );

        // Cargo is claimed in destination port
        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );

        // No more expected handling events
        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
    }
}