﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace BookReviews.UI.Saga
{
    public class OrderDetailsRequestSaga :
	    SagaStateMachine<OrderDetailsRequestSaga>, ISaga
    {
	    static OrderDetailsRequestSaga()
	    {
		    Define(Saga);
	    }

        private static void Saga()
	    {
		    Correlate(RequestReceived)
			    .By((saga, message) => saga.CustomerId == message.CustomerId &&
			                            saga.OrderId == message.OrderId &&
			                            saga.CurrentState == WaitingForResponse);

		    Correlate(ResponseReceived)
			    .By((saga, message) => saga.CustomerId == message.CustomerId &&
			                            saga.OrderId == message.OrderId &&
			                            saga.CurrentState == WaitingForResponse);

        public static State Initial { get; set; }
	    public static State WaitingForResponse { get; set; }
	    public static State Completed { get; set; }
        public static Event<RetrieveOrderDetails> RequestReceived { get; set; }
	    public static Event<OrderDetailsResponse> ResponseReceived { get; set; }
	    public static Event<OrderDetailsRequestFailed> RequestFailed { get; set; }

        Initially(
			When(RequestReceived)
				.Then((saga, request) =>
					{
						saga.OrderId = request.OrderId;
						saga.CustomerId = request.CustomerId;
					})
				.Publish((saga, request) => new SendOrderDetailsRequest
					{
						RequestId = saga.CorrelationId,
						CustomerId = saga.CustomerId,
						OrderId = saga.OrderId,
					})
				.TransitionTo(WaitingForResponse));

        During(WaitingForResponse,
			When(ResponseReceived)
				.Then((saga, response) =>
					{
						saga.OrderCreated = response.Created;
						saga.OrderStatus = response.Status;
					})
				.Publish((saga, request) => new OrderDetails
					{
						CustomerId = saga.CustomerId,
						OrderId = saga.OrderId,
						Created = saga.OrderCreated.Value,
						Status = saga.OrderStatus,
					})
				.TransitionTo(Completed));
	    }

        public OrderDetailsRequestSaga(Guid correlationId)
	    {
		    CorrelationId = correlationId;
	    }

	    protected OrderDetailsRequestSaga()
	    {
	    }

	    public virtual string CustomerId { get; set; }
	    public virtual string OrderId { get; set; }
	    public virtual OrderStatus OrderStatus { get; set; }
	    public virtual DateTime? OrderCreated { get; set; }
	
	    public virtual Guid CorrelationId { get; set; }
	    public virtual IServiceBus Bus { get; set; }
        }

        //The rest of the saga class is shown above for completeness. 
        //The properties are part of the saga and get saved when the saga is persisted 
        //(using the NHibernate saga persister, or in the case of the sample the in-memory implementation). 
        //The constructor with the Guid is used to initialize the saga when a new one is created, 
        //the protected one is there for NHibernate to be able to persist the saga. 
    }
}