public List<ServiceCarInsuranceQuoteResponse> CreateQuotes(ServiceCarInsuranceQuoteRequest request)
 {
     return CalculateQuote(request)
          .Select(x => new ServiceCarInsuranceQuoteResponse
          {
              QuoteId = request.QuoteRequestId,
              QuoteType = x.Key,
              InsuranceCompany = request.Insurer.GetDisplayName(),
              QuoteDescription = x.Key.GetDisplayName(),
              QuoteValue = x.Value
          }).ToList();
 }
        /// <summary>
        /// todo: build in some logic to determine a more random set of prices determined by the quote factors
        /// out of scope for now
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private Dictionary<QuoteType, decimal> CalculateQuote(ServiceCarInsuranceQuoteRequest request)
        {
            Thread.Sleep(2000); // add a 2 second delay

            var quotePrices = new Dictionary<QuoteType, decimal>();
            switch (request.Insurer)
            {
                case Insurer.AllianceDirect:
                    quotePrices.Add(QuoteType.Comprehensive, BuildQuote((decimal)400, request));
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, BuildQuote((decimal)370, request));
                    quotePrices.Add(QuoteType.ThirdParty, BuildQuote((decimal)310, request));
                    break;
                case Insurer.AxaCar:
                    // Add a further 10 second delay for the Axa Service (Test)
                  //  throw new ServerException("Forced Exception");
                  //  Thread.Sleep(10000);
                    quotePrices.Add(QuoteType.Comprehensive, BuildQuote((decimal)420, request));
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, BuildQuote((decimal)350, request));
                    quotePrices.Add(QuoteType.ThirdParty, BuildQuote((decimal)300, request));
                    break;
                case Insurer.ZurichCar:
                    quotePrices.Add(QuoteType.Comprehensive, BuildQuote((decimal)380, request));
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, BuildQuote((decimal)360, request));
                    quotePrices.Add(QuoteType.ThirdParty, BuildQuote((decimal)320, request));
                    break;
                case Insurer.OneTwoThree:
                    quotePrices.Add(QuoteType.Comprehensive, BuildQuote((decimal)500, request));
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, BuildQuote((decimal)407, request));
                    quotePrices.Add(QuoteType.ThirdParty, BuildQuote((decimal)245, request));
                    break;
                case Insurer.Fbd:
                    quotePrices.Add(QuoteType.Comprehensive, BuildQuote((decimal)430, request));
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, BuildQuote((decimal)390, request));
                    quotePrices.Add(QuoteType.ThirdParty, BuildQuote((decimal)350, request));
                    break;
                default:
                    quotePrices.Add(QuoteType.Comprehensive, (decimal)0);
                    quotePrices.Add(QuoteType.ThirdPartyFireAndTheft, (decimal)0);
                    quotePrices.Add(QuoteType.ThirdParty, (decimal)0);
                    break;
            }

            return quotePrices;
        }
        public async Task<HttpResponseMessage> Post(ServiceCarInsuranceQuoteRequest request)
        {
            try
            {
                ICreateQuoteService quoteService = new CreateQuoteService();

                _logger.Debug(JsonConvert.SerializeObject(request));

                var quotesReturned = await Task.FromResult<List<ServiceCarInsuranceQuoteResponse>>(quoteService.CreateQuotes(request));

                _logger.Debug(JsonConvert.SerializeObject(quotesReturned));

                return Request.CreateResponse(HttpStatusCode.OK, quotesReturned);
            }
            catch (Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
            }
        }
        private decimal BuildQuote(decimal baseQuote, ServiceCarInsuranceQuoteRequest request)
        {
            var riskPremium = baseQuote + VehicleAgePremium(request.ManufYear) + DriverHighRiskPremium(request.DriverAge) + VehicleValuePremium(request.ManufYear);

            return HighRiskOfTheftPremium(riskPremium, request.County);
        }
        private void MessageReceiver()
        {
            Receive<RequestQuotes>(req =>
            {
                // write the initial request to the db.
                Task<int> quoteId = _carQuoteRequestWriter.AddQuote(req.QuoteRequest).ContinueWith(s => s.Result);

                _quoteResults.Clear(); // clean down any previous results
                _serviceTimer.Start(); // start the timer.
                _isLoadComplete = false;

                // push the service request message to the service workers
                foreach (var insurer in Enum.GetValues(typeof (Insurer)))
                {
                    // build the object to post
                    var serviceRequest = new ServiceCarInsuranceQuoteRequest
                    {
                        QuoteRequestId = quoteId.Result, // created quoteId
                        NoClaimsDiscountYears =
                            req.QuoteRequest.NoClaimsDiscountYears.HasValue
                                ? req.QuoteRequest.NoClaimsDiscountYears.Value
                                : 0,
                        VehicleValue = req.QuoteRequest.VehicleValue.HasValue ? req.QuoteRequest.VehicleValue.Value : 0,
                        CurrentRegistration = req.VehicleDetails.CurrentRegistration,
                        DriverAge = req.QuoteRequest.DriverAge.HasValue ? req.QuoteRequest.DriverAge.Value : 0,
                        ModelDesc = req.VehicleDetails.ModelDesc,
                        IsImport = req.VehicleDetails.IsImport,
                        ManufYear = req.VehicleDetails.ManufYear.HasValue ? req.VehicleDetails.ManufYear.Value : 0,
                        Insurer = (Insurer) insurer
                    };

                    _quoteServicesPool.Tell(new GetQuotesFromService(req.ServiceLocation, serviceRequest));

                    _log.Debug("Fired Request for {0}", insurer);
                }

                this.Sender.Tell(quoteId.Result); // pass the quoteId back to the controller
            });

            // Listener for QuoteServices Results. Append to Results Collection and sort as required
            Receive<QuotesReturnedFromService>(req =>
            {
                if (req == null)
                    return;

                _log.Debug("Appending {0} Logs", req.QuotesFromService.Count);

                _quoteResults.AddRange(req.QuotesFromService);

                int insurersReturned = _quoteResults.GroupBy(x => x.Insurer).Count();
                if (_numInsurers.Equals(insurersReturned))
                    this.Sender.Tell(new TimedOutOrComplete(isComplete: true));
            });

            Receive<TimedOutOrComplete>(req =>
            {
                if (req.IsTimedOut && req.IsComplete) // not interested in a response post timeout
                    return;

                // sort the collated results only if all insurers have returned or if
                // the time out has been reached.
                if (req.IsTimedOut || req.IsComplete)
                {
                    var cheapestQuotes = _quoteResults
                        .GroupBy(x => x.QuoteType)
                        .SelectMany(y => y.OrderBy(x => x.QuoteValue)
                            .Take(1));

                    // set ischeapest flag for UI
                    foreach (var quote in _quoteResults)
                    {
                        if (cheapestQuotes.Contains(quote))
                        {
                            quote.IsCheapest = true;
                        }
                    }

                    // persist results and pass the bool result back to this Actor which will set the IsLoadComplete flag
                    _carQuoteResponseWriter.AddResponse(_quoteResults).ContinueWith(s => s.Result).PipeTo(Self);
                }
            });

            Receive<bool>(req => { _isLoadComplete = req; }); // success bool piped from write to Db query above

            Receive<IsLoadComplete>(req => this.Sender.Tell(_isLoadComplete)); // is Complete Flag set Request

            Receive<ListQuotes>(req => // pass back the complete result set once everything has been persisted.
            {
                if (_isLoadComplete)
                    Sender.Tell(_quoteResults);

                Sender.Tell(null);
            });
        }