/// <summary>
        /// Generate Email Model method
        /// </summary>
        /// <returns> The <see cref="DealsEmailModel"/>. </returns>
        /// <exception cref="ModelContentException"> The input is insufficient for email model creation </exception>
        public DailyDealsContract GenerateModel(EmailTemplateData modelData)
        {
            DailyDealsContract dailyDealsContract  = null;
            DealsTemplateData  dailyDealsModelData = modelData as DealsTemplateData;

            if (dailyDealsModelData != null)
            {
                var            dealsList     = dailyDealsModelData.Deals == null ? null : dailyDealsModelData.Deals.ToList();
                DealContract[] dealsContract = null;
                if (dealsList != null)
                {
                    if (dailyDealsModelData.DealEmailType == DealEmailType.WeeklyDeal && dealsList.Count() <= 3)
                    {
                        throw new ModelContentException(string.Format("Number of deals is: {0}. This is insufficient for email model creation", dealsList.Count()));
                    }

                    dealsContract = new DealContract[dealsList.Count];
                    for (int i = 0; i < dealsList.Count; ++i)
                    {
                        DealContract dealContract = ConvertDeal(dealsList[i]);
                        if (dealContract != null)
                        {
                            dealsContract[i] = dealContract;
                        }
                    }

                    if (dailyDealsModelData.DealEmailType == DealEmailType.WeeklyDeal && dealsContract.Length <= 3)
                    {
                        throw new ModelContentException(string.Format("Number of deals is: {0}. This is insufficient for email model creation", dealsList.Count()));
                    }
                }

                var location    = Users.Dal.DataModel.Location.Parse(dailyDealsModelData.LocationId);
                var locationStr = string.Empty;
                if (location.Type == LocationType.Postal || location.Type == LocationType.City)
                {
                    Log.Info("Getting Location for user: {0}, locationId: {1}", dailyDealsModelData.EmailAddress, dailyDealsModelData.LocationId);
                    var geoCodePoint = GeoSpatial.GetGeoData(WebUtility.HtmlEncode(string.Format("{0} {1} {2}", location.CountryCode, location.AdminDistrict, location.Value)), GeoSpatial.GeoSource.VirtualEarth);
                    if (geoCodePoint != null && geoCodePoint.Location != null)
                    {
                        locationStr = geoCodePoint.Location.Locality;
                        Log.Info("Retrieved Location info : {0} for user: {1}, locationId: {2}", locationStr, dailyDealsModelData.EmailAddress, dailyDealsModelData.LocationId);
                    }
                    else
                    {
                        Log.Warn("Couldn't fetch location data for user: {0}, locationId: {1}", dailyDealsModelData.EmailAddress, location);
                    }
                }

                dailyDealsContract = new DailyDealsContract {
                    UnsubscribeUrl = dailyDealsModelData.UnsubscribeUrl, Deals = dealsContract, Location = locationStr
                };
            }

            return(dailyDealsContract);
        }
        /// <summary>
        /// The get content.
        /// </summary>
        /// <param name="emailCargo">
        /// The email Job.
        /// </param>
        /// <returns>
        /// The <see cref="EmailContent"/>.
        /// </returns>
        /// <exception cref="TemplateRenderException">
        /// error while rendering the template
        /// </exception>
        public EmailData GetContent(object emailCargo)
        {
            EmailData       emailData       = null;
            DealsEmailCargo dealsEmailCargo = emailCargo as DealsEmailCargo;

            if (dealsEmailCargo != null)
            {
                string locationId            = dealsEmailCargo.LocationId;
                bool   isSendTimeWindowValid = true;
                IEnumerable <UserEmailEntity> emailHistoryEntities = null;

                //If this is not a test email, check the history to make sure we are not sending the email to the same user within the sendtime window.
                if (!dealsEmailCargo.Hints.IsTestEmail)
                {
                    emailHistoryEntities  = this.userHistoryStorage.GetUserEmailEntities(dealsEmailCargo.UserId, mailHistoryLookback).ToList();
                    isSendTimeWindowValid = this.IsSendTimeWindowValid(emailHistoryEntities.FirstOrDefault(elem => elem.LocationId == locationId), dealsEmailCargo);
                }
                if (isSendTimeWindowValid)
                {
                    IEnumerable <Guid> dealsToExclude = null;
                    //if dealids are not included the cargo, we have to select random deals. Need to check in the history to make sure we are excluding deals that have
                    //already been sent in the past few weeks (based on the mail history lookback settings)
                    if (emailHistoryEntities != null && dealsEmailCargo.DealIds == null)
                    {
                        dealsToExclude = this.GetDealsToExclude(emailHistoryEntities);
                    }

                    EmailRenderingClient <DailyDealsContract> emailRenderingClient = new EmailRenderingClient <DailyDealsContract>
                    {
                        EmailRenderingServiceUrl = dealsEmailCargo.EmailRenderingServiceAddress
                    };
                    IEnumerable <Deal> deals = null;
                    if (dealsEmailCargo.Hints != null && dealsEmailCargo.Hints.IncludeDeals)
                    {
                        deals = this.dealsSelector.GetDeals(emailCargo as DealsEmailCargo, dealsToExclude).ToList();
                    }
                    if (deals != null && deals.Any())
                    {
                        DealsTemplateData dailyDealsTemplateData = new DealsTemplateData
                        {
                            EmailAddress   = dealsEmailCargo.EmailAddress,
                            UnsubscribeUrl = dealsEmailCargo.UnsubscribeUrl,
                            LocationId     = locationId,
                            Deals          = deals,
                            DealEmailType  =
                                dealsEmailCargo.DealIds != null && dealsEmailCargo.DealIds.Any()
                                        ? DealEmailType.TrendingDeal
                                        : DealEmailType.WeeklyDeal
                        };

                        var model = this.templateModelCreator.GenerateModel(dailyDealsTemplateData);
                        emailData = new EmailData
                        {
                            Subject = !string.IsNullOrEmpty(dealsEmailCargo.Subject)
                                              ? dealsEmailCargo.Subject
                                              : this.RenderSubject(model),
                            HtmlBody = emailRenderingClient.RenderHtml(model),
                            TextBody = string.Empty,
                            DealIds  = deals.Select(elem => new Guid(elem.Id)).ToList()
                        };
                    }
                    else
                    {
                        int dealsCount = deals != null?deals.Count() : 0;

                        throw new ModelContentException(string.Format("Number of deals is: {0}. This is insufficient for email model creation", dealsCount));
                    }
                }
            }

            return(emailData);
        }