/// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            List<long> prospects = new List<long>();
            EntityCollection<OrderStateRadius> orders = runtime.GetData(ExchangeRuntime.ORDER_STATES) as EntityCollection<OrderStateRadius>;
            OutboundDuplicateEvent @event = new OutboundDuplicateEvent(this.GetType().Name);

            foreach (OrderStateRadius radius in orders)
            {
                if (ExchangeService.IsOutboundDuplicate(runtime.GetLead().Email, radius.Aid))
                {
                    @event.Aid = radius.Aid;
                    @event.Duplicate = true;
                    continue;
                }
                prospects.Add(radius.OrderId);
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.StoreData(ExchangeRuntime.PROSPECTS, prospects);
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            List<long> prospects = runtime.GetData(ExchangeRuntime.DISTRIBUTIONS) as List<long>;

            DistributionEvent @event = new DistributionEvent(this.GetType().Name);

            if (prospects != null)
            {
                foreach (long prospect in prospects)
                {
                    DeliveryQueue queue = new DeliveryQueue();
                    queue.AdvertiserId = prospect;
                    queue.Disposition = "PENDING";
                    queue.LeadId = runtime.GetLead().Id;

                    ExchangeService.SaveDeliveryQueue(queue);
                    @event.Advertisers.Add(prospect);
                }
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            EntityCollection<OrderStateRadius> radius = ExchangeService.GetOrderStateRadiusByState(runtime.GetLead().State);

            if (radius.Count() == 0)
            {
                runtime.PendingMatch = true;
                return;
            }

            DistanceEvent @event = new DistanceEvent(this.GetType().Name);
            @event.State = runtime.GetLead().State;

            foreach (OrderStateRadius state in radius)
            {
                // @event.Orders.Add(state.OrderId);
                @event.BidOrders.Add(new Bid(state.Aid, state.OrderId));
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.StoreData(ExchangeRuntime.ORDER_STATES, radius);
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            VintageEvent @event = new VintageEvent(this.GetType().Name);

            if (runtime.AllocationCount == 0)
            {
                runtime.Status = ExchangeRuntime.PENDING_MATCH;
            }

            // TODO: extract to method.
            if (runtime.AllocationCount < 4)
            {
                VintageDebtLead lead = new VintageDebtLead();
                lead.LeadId = runtime.GetLead().Id;
                lead.Status = "PENDING";

                ExchangeService.SaveVintageDebtLead(lead);
                @event.BuyRate = runtime.AllocationCount;
                @event.Vintage = true;
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                // runtime.Status = ExchangeEngine.
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            PricingEvent @event = new PricingEvent(this.GetType().Name);
            string debtamount = runtime.GetDebtLead().CreditCardDebtAmount;
            string daysbehind = runtime.GetDebtLead().PaymentStatus;
            Console.WriteLine("amount={0}, days={1}.", debtamount, daysbehind);
            List<long> prospects = runtime.GetData(ExchangeRuntime.PROSPECTS) as List<long>;

            EntityCollection<Allocation> allocations = ExchangeService.GetAllocationPlan(prospects, debtamount, daysbehind);
            if (allocations == null)
            {
                runtime.Status = ExchangeRuntime.PENDING_MATCH;
                timer.Stop();
                @event.ElapsedTime = timer.ElapsedMilliseconds;
                runtime.AllocationCount = 0;
                runtime.AddStrategyEvent(@event);
                runtime.Continue();
                return;
            }

            List<long> distributions = new List<long>();

            foreach (Allocation prospect in allocations)
            {
                OutboundDuplicate outDupe = new OutboundDuplicate();
                outDupe.Aid = Convert.ToString(prospect.Aid);
                outDupe.Oid = Convert.ToString(prospect.OrderId);
                outDupe.Email = runtime.GetLead().Email;
                outDupe.Created = runtime.GetLead().Created;
                ExchangeService.SaveOutboundDuplicate(outDupe);

                distributions.Add(prospect.Aid);
                @event.Bids.Add(new Bid(prospect.Aid, prospect.OrderId));
            }

            if (allocations.Count() > 0)
            {
                runtime.Status = ExchangeRuntime.ACCEPTED;
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.StoreData(ExchangeRuntime.DISTRIBUTIONS, distributions);
            runtime.AllocationCount = allocations.Count();
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtimme"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            // NOTE: this could throw an invalid cast exception if bad developer makes a mistake from ExchangeEngine.
            DebtLeadEvent @event = new DebtLeadEvent("");
            @event.Lead = runtime.GetLead() as DebtLead;

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            ImpoundEvent @event = new ImpoundEvent(this.GetType().Name);
            @event.Impounded = false;

            if (ExchangeService.IsSuspectPublisher(runtime.GetLead().Aid))
            {
                SuspectDebtLead lead = new SuspectDebtLead();
                lead.Guid = runtime.GetLead().Guid;
                lead.Aid = runtime.GetLead().Aid;
                lead.Cid = runtime.GetLead().Cid;
                lead.Sid = runtime.GetLead().Sid;
                lead.Tid = runtime.GetLead().Tid;
                lead.FirstName = runtime.GetLead().FirstName;
                lead.LastName = runtime.GetLead().LastName;
                lead.Email = runtime.GetLead().Email;
                lead.Phone = runtime.GetLead().Phone;
                lead.SecondaryPhone = runtime.GetLead().SecondaryPhone;
                lead.Street = runtime.GetLead().Street;
                lead.City = runtime.GetLead().City;
                lead.Zip = runtime.GetLead().Zip;
                lead.State = runtime.GetLead().State;
                lead.Created = runtime.GetLead().Created;
                lead.CreditCardDebtAmount = ((DebtLead) runtime.GetLead()).CreditCardDebtAmount;
                lead.UnsecuredDebtAmount = ((DebtLead)runtime.GetLead()).UnsecuredDebtAmount;
                lead.PaymentStatus = ((DebtLead)runtime.GetLead()).PaymentStatus;
                lead.MonthlyPayments = ((DebtLead)runtime.GetLead()).MonthlyPayments;

                ExchangeService.SaveImpound(lead);
                runtime.IsSuspect = true;
                runtime.Status = ExchangeRuntime.PENDING_VERIFICATION;
                @event.Impounded = true;
                @event.Aid = Convert.ToInt64(runtime.GetLead().Aid);
                return;
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            Reduce(runtime);

            timer.Stop();
            if (logger.IsInfoEnabled)
            {
                logger.InfoFormat("gateway elapsed time: {0}.", timer.ElapsedMilliseconds);
            }

            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            //Stopwatch timer = new Stopwatch();
            //timer.Start();

            AggregatedContribution contribution = SearchEngineGateway.CalculateAggregatedCostAndClickContribution();

            if (contribution.Compare((cost, click) => cost > 25 && click > 30) || contribution.Compare((cost, click) => cost > 25 && click <= 30))
            {
                SearchEngineGateway.PauseAccount();
            }
            else if (contribution.Compare((cost, click) => cost <= 25 && click <= 30) || contribution.Compare((cost, click) => cost > 25 && click <= 30))
            {
                SearchEngineGateway.ChangeBidToMostRelevantCombinationForPositiveROI();
            }

            //timer.Stop();
            //@event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (runtime.Abort)
            {
                runtime.Continue();
                return;
            }

            Stopwatch timer = new Stopwatch();
            timer.Start();

            InboundDuplicateEvent @event = new InboundDuplicateEvent(this.GetType().Name);
            @event.Duplicate = false;
            runtime.AddStrategyEvent(@event);

            if (ExchangeService.IsInboundDuplicate(runtime.GetLead().Email))
            {
                runtime.IsInboundDuplicate = true;
                @event.Duplicate = true;
                @event.Aid = Convert.ToInt64(runtime.GetLead().Aid);

                runtime.Status = ExchangeRuntime.DUPLICATE;
                runtime.Abort = true;
            }
            else
            {
                InboundDuplicate duplicate = new InboundDuplicate();
                duplicate.Email = runtime.GetLead().Email;
                duplicate.PublisherId = runtime.GetLead().Aid;
                duplicate.Created = runtime.GetLead().Created;

                ExchangeService.SaveInboundDuplicate(duplicate);
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            if (!SearchEngineGateway.HasLostConversions())
            {
                runtime.Continue();
                return;
            }

            if (SearchEngineGateway.IsCurrentAndHistoricalPositionTheSame())
            {
                if (SearchEngineGateway.HasAdCopyChanged())
                {
                    SearchEngineGateway.AlertAdCopyChangeRollback();
                }
                else
                {
                    SearchEngineGateway.AlertPotentialLandingPageChanges();
                }
            }
            else
            {
                SearchEngineGateway.ChangeBidToMostRelevantCombinationForPositiveROI();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            ValidationEvent @event = new ValidationEvent(this.GetType().Name);
            @event.Valid = true;

            if ("DEBT".Equals(runtime.Vertical))
            {
                DebtLead lead = runtime.GetLead() as DebtLead;
                List<Error> errors = DebtValidator.Validate(lead, runtime.LeadSource);

                if (errors.Count > 0)
                {
                    @event.Valid = false;
                    @event.Errors = errors;

                    runtime.Status = ExchangeRuntime.INVALID;
                    runtime.ValidationErrors = errors;
                    runtime.Abort = true;
                }
            }

            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            NotificationEvent @event = new NotificationEvent(this.GetType().Name);
            @event.From = From;
            @event.To = Recipient;
            @event.Subject = Subject;

            string body = runtime.GetData(DataKey) as string;
            EmailGateway.SendHtml(Host, From, Recipient, Subject, body);

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// TODO: need to figure out how to add current strategy to soap message. 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            SaverEvent @event = new SaverEvent(this.GetType().Name);

            string xml = ExchangeTracker.CreateSoapMessage(runtime);
            string filename = Utility.CreateFileName(DateTime.Now, Context, Status, runtime.GetLead().Guid);
            FileInfo file = new FileInfo(filename);
            StreamWriter writer = file.CreateText();
            writer.Write(xml);
            writer.Close();

            @event.Filename = filename;
            @event.Context = Context;
            @event.Status = Status;
            @event.Content = xml;

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            DispositionTrackerEvent @event = new DispositionTrackerEvent();

            string body = runtime.GetData(DataKey) as string;
            ExchangeTracker.TrackComplete(string.Format("{0}-{1}", runtime.Vertical, runtime.VerticalType), runtime.Status, runtime, body);

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            string xml = ExchangeTracker.CreateSoapMessage(runtime);

            XslCompiledTransform transformer = new XslCompiledTransform();
            transformer.Load(template);

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            StringWriter writer = new StringWriter();
            XmlTextWriter xmlWriter = new XmlTextWriter(writer);
            transformer.Transform(doc, xmlWriter);
            string result = writer.ToString();

            runtime.StoreData(ResultKey, result);

            TransformerEvent @event = new TransformerEvent(this.GetType().Name);
            @event.Template = template;
            @event.Result = result;
            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            DebtLead result = ExchangeService.SaveDebtLead(runtime.GetLead() as DebtLead);
            runtime.GetLead().Id = result.Id;

            PersistenceEvent @event = new PersistenceEvent(this.GetType().Name);
            @event.Lead = runtime.GetLead();

            //if (logger.IsDebugEnabled)
            //{
            //    logger.DebugFormat("persisting inbound duplicate for publiser: {0}, lead: {1}.", runtime.GetLead().Aid, runtime.GetLead().Email);
            //}

            //InboundDuplicate dupe = new InboundDuplicate();
            //dupe.PublisherId = runtime.GetLead().Aid;
            //dupe.Email = runtime.GetLead().Email;
            //dupe.Created = runtime.GetLead().Created;
            //DuplicateDataAccess.SaveInboundDuplicate(dupe);

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="context"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            CleanerEvent @event = new CleanerEvent();

            Stopwatch timer = new Stopwatch();
            timer.Start();

            XmlDocument xml = runtime.GetData(key) as XmlDocument;

            foreach (XmlNode node in xml.SelectNodes(Axis))
            {
                string targetValue = node.SelectSingleNode(Target).InnerText;

                foreach (string value in Values)
                {
                    if (value.ToLower() == targetValue.ToLower())
                    {
                        node.ParentNode.RemoveChild(node);
                        break;
                    }
                }
            }

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.Continue();
        }
        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="runtime"></param>
        /// 
        public override void Invoke(ExchangeRuntime runtime)
        {
            Stopwatch timer = new Stopwatch();
            timer.Start();

            MessageGatewayEvent @event = new MessageGatewayEvent(this.GetType().Name);

            string xml = ExchangeTracker.CreateSoapMessage(runtime);
            MessageGateway<string> gateway = new MessageGateway<string>(Destination);
            gateway.Send(xml);

            @event.Destination = Destination;
            @event.Content = xml;

            timer.Stop();
            @event.ElapsedTime = timer.ElapsedMilliseconds;
            runtime.AddStrategyEvent(@event);
            runtime.Continue();
        }