internal protected ActiveCreative GetCreative(ICreativeSource adSource, IAdTarget adTarget)
        {
            IVpaid adPlayer;
            var    vPaidFactories = GetVpaidFactories().ToList();

            do
            {
                var rankedVpaidFactories =
                    from factory in vPaidFactories
                    let rank = factory.CheckSupport(adSource, adTarget)
                               where rank > PriorityCriteriaEnum.NotSupported
                               orderby rank descending
                               select factory;

                var playerFactory = rankedVpaidFactories.FirstOrDefault();
                if (playerFactory == null)
                {
                    return(null);
                }

                adPlayer = playerFactory.GetVpaidPlayer(adSource, adTarget);

                // handshake with the ad player to make sure the version of VAST is OK
                if (adPlayer == null || !VpaidController.Handshake(adPlayer))
                {
                    // the version is no good, remove the factory from the list and try again.
                    vPaidFactories.Remove(playerFactory);
                    if (!vPaidFactories.Any())
                    {
                        return(null);
                    }
                    adPlayer = null;
                }
            } while (adPlayer == null);

            //put companion in target
            if (!adTarget.AddChild(adPlayer))
            {
                return(null);
            }

            return(new ActiveCreative(adPlayer, adSource, adTarget));
        }
        public ActiveCreative GetLinearCreative(VASTADInLineCreativeLinear linear, IAdTarget adTarget, VASTADInLine ad, params VASTADWrapper[] wrappers)
        {
            IVpaid adPlayer;
            ICreativeSource adSource;
            var vPaidFactories = VastAdHandler.GetVpaidFactories().ToList();
            do
            {
                // get a list of all eligible media files
                var mediaAdSources = linear.MediaFiles.ToDictionary(m => m, m => new LinearSource(ad, m, linear, wrappers));

                var rankedMedia =
                    (from mediaAdSource in mediaAdSources
                     let vPaidFactoryAndPriority = vPaidFactories.ToDictionary(f => f, f => f.CheckSupport(mediaAdSource.Value, adTarget))
                     where vPaidFactoryAndPriority.Values.Any(v => v > PriorityCriteriaEnum.NotSupported)
                     let BestVpaidFactoryAndPriority = vPaidFactoryAndPriority.OrderByDescending(kvp => kvp.Value).First()
                     let rank = BestVpaidFactoryAndPriority.Value
                     orderby rank descending
                     select new
                     {
                         MediaFile = mediaAdSource.Key,
                         AdSource = mediaAdSource.Value,
                         VpaidFactory = BestVpaidFactoryAndPriority.Key,
                         Rank = rank,
                     }).ToList();

                if (rankedMedia.Any())
                {
                    // get all media with the best rankings
                    var topRank = rankedMedia.First().Rank;
                    var bestMedia = rankedMedia.Where(m => m.Rank == topRank);

                    // favor adaptive media
                    var adaptiveMedia = bestMedia.Where(m => m.MediaFile.delivery == VASTADInLineCreativeLinearMediaFileDelivery.streaming);
                    if (adaptiveMedia.Any())
                        bestMedia = adaptiveMedia;

                    double targetBitrateKbps = (double)VastAdHandler.AdHost.PlaybackBitrate / 1024;
                    if (targetBitrateKbps == 0.0)
                    {
                        // progressive videos won't have a bitrate. Therefore, target based on the one in the middle
                        targetBitrateKbps = rankedMedia.Where(m => m.MediaFile.bitrate.ToInt64().HasValue).Average(m => m.MediaFile.bitrate.ToInt64().Value);
                    }

                    // get the media with the closest bitrate
                    var bitrateMedia = bestMedia
                        .Where(m => m.MediaFile.bitrate.ToInt64().HasValue)
                        .GroupBy(m => Math.Abs(m.MediaFile.bitrate.ToInt64().Value))
                        .OrderBy(m => m.Key <= MaxBitrateKbps ? 0 : m.Key - MaxBitrateKbps)
                        .ThenBy(m => Math.Abs(m.Key - targetBitrateKbps))
                        .FirstOrDefault();
                    if (bitrateMedia != null && bitrateMedia.Any())
                        bestMedia = bitrateMedia;

                    //// get the media with the closest bitrate
                    //var selectedMedia = bestMedia
                    //    .Where(m => !string.IsNullOrEmpty(m.MediaFile.bitrate))
                    //    .OrderBy(m => Math.Abs(long.Parse(m.MediaFile.bitrate) - VastAdHandler.AdHost.PlaybackBitrate))
                    //    .FirstOrDefault();

                    // get the media with the closest size
                    var sizedMedia =
                        from m in bestMedia
                        where m.MediaFile.height.ToInt64().HasValue && m.MediaFile.width.ToInt64().HasValue
                        let x = VastAdHandler.AdHost.VideoArea.ActualHeight - m.MediaFile.height.ToInt64().Value
                        let y = VastAdHandler.AdHost.VideoArea.ActualWidth - m.MediaFile.width.ToInt64().Value
                        let delta = x + y
                        orderby delta
                        select new { Media = m, DeltaX = x, DeltaY = y };

                    // try to get the one with the closest size but both dimensions are within the current size
                    var selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 && sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size where only one dimension is over the current size
                        selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 || sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size
                        selectedMedia = sizedMedia.Select(sm => sm.Media).LastOrDefault();

                    // see if there were any bitrates, if not grab which ever one was first in the VAST file
                    if (selectedMedia == null)
                        selectedMedia = bestMedia.First();

                    //finally, get the ad player
                    adSource = selectedMedia.AdSource;
                    adPlayer = selectedMedia.VpaidFactory.GetVpaidPlayer(adSource, adTarget);

                    if (adPlayer == null)
                    {
                        //Log.Output(OutputType.Error, "Error - cannot find player to support video ad content. ");
                        // this should never happen and is the result of a bad VPaid plugin.
                        throw new Exception("VpaidFactory agreed to accept AdSource and then returned null during call to GetVPaidPlugin.");
                    }
                    // handshake with the ad player to make sure the version of VAST is OK
                    if (adPlayer == null || !vastAdHandler.VpaidController.Handshake(adPlayer))
                    {
                        // the version is no good, remove the factory from the list and try again.
                        vPaidFactories.Remove(selectedMedia.VpaidFactory);
                        if (!vPaidFactories.Any())
                        {
                            return null;
                        }
                        adPlayer = null;
                    }
                }
                else
                {
                    return null;
                }
            } while (adPlayer == null);

            //put video in target
            if (!adTarget.AddChild(adPlayer))
            {
                return null;
            }

            return new ActiveCreative(adPlayer, adSource, adTarget);
        }
        internal protected ActiveCreative GetCreative(ICreativeSource adSource, IAdTarget adTarget)
        {
            IVpaid adPlayer;
            var vPaidFactories = GetVpaidFactories().ToList();
            do
            {
                var rankedVpaidFactories =
                from factory in vPaidFactories
                let rank = factory.CheckSupport(adSource, adTarget)
                where rank > PriorityCriteriaEnum.NotSupported
                orderby rank descending
                select factory;

                var playerFactory = rankedVpaidFactories.FirstOrDefault();
                if (playerFactory == null) return null;

                adPlayer = playerFactory.GetVpaidPlayer(adSource, adTarget);

                // handshake with the ad player to make sure the version of VAST is OK
                if (adPlayer == null || !VpaidController.Handshake(adPlayer))
                {
                    // the version is no good, remove the factory from the list and try again.
                    vPaidFactories.Remove(playerFactory);
                    if (!vPaidFactories.Any())
                    {
                        return null;
                    }
                    adPlayer = null;
                }
            } while (adPlayer == null);

            //put companion in target
            if (!adTarget.AddChild(adPlayer))
            {
                return null;
            }

            return new ActiveCreative(adPlayer, adSource, adTarget);
        }
        ActiveCreative GetLinearCreative(IAdTarget adTarget, AdPackage pkgElement, bool addToTarget)
        {
            IVpaid adPlayer = null;
            ICreativeSource adSource = null ;
            var vPaidFactories = AdHandler.GetVpaidFactories().ToList();
            do
            {
                // get a list of all eligible media files
                var mediaAdSources = pkgElement.VideoResources.ToDictionary(
                    m => m as VideoResource, m => new AdCreativeSource(pkgElement, m));

                var rankedMedia =
                    (from mediaAdSource in mediaAdSources
                     let vPaidFactoryAndPriority = vPaidFactories.ToDictionary(f => f,
                     f => f.CheckSupport(mediaAdSource.Value, adTarget))
                     where vPaidFactoryAndPriority.Values.Any(v => v > PriorityCriteriaEnum.NotSupported)
                     let BestVpaidFactoryAndPriority = vPaidFactoryAndPriority.OrderByDescending(kvp => kvp.Value).First()
                     let rank = BestVpaidFactoryAndPriority.Value
                     orderby rank descending
                     select new
                     {
                         MediaFile = mediaAdSource.Key,
                         AdSource = mediaAdSource.Value,
                         VpaidFactory = BestVpaidFactoryAndPriority.Key,
                         Rank = rank,
                     }).ToList();

                if (rankedMedia.Any())
                {
                    // get all media with the best rankings
                    var topRank = rankedMedia.First().Rank;
                    var bestMedia = rankedMedia.Where(m => m.Rank == topRank);

                    // favor adaptive media if IsSmoothEnabled flag is set. Default is true.
                    var adaptiveMedia = bestMedia.Where(m => m.AdSource.IsStreaming);
                    var nonAdaptiveMedia = bestMedia.Except(adaptiveMedia);
                    if (AdHandler.IsSmoothEnabled)
                    {
                        if (adaptiveMedia.Any()) bestMedia = adaptiveMedia;
                    }
                    else
                    {
                        if (nonAdaptiveMedia.Any()) bestMedia = nonAdaptiveMedia;
                    }

                    double targetBitrateKbps = (double)AdHandler.AdHost.PlaybackBitrate / 1024;
                    if (targetBitrateKbps == 0.0)
                    {
                        // progressive videos won't have a bitrate. Therefore, target based on the one in the middle
                        targetBitrateKbps = rankedMedia.Average(m => m.MediaFile.Bitrate);
                    }

                    // get the media with the closest bitrate
                    var bitrateMedia = bestMedia
                        .GroupBy(m => Math.Abs(m.MediaFile.Bitrate))
                        .OrderBy(m => m.Key <= AdHandler.MaxBitrateKbps ? 0 : m.Key - AdHandler.MaxBitrateKbps)
                        .ThenBy(m => Math.Abs(m.Key - targetBitrateKbps))
                        .FirstOrDefault();
                    if (bitrateMedia != null && bitrateMedia.Any())
                        bestMedia = bitrateMedia;

                    // get the media with the closest size
                    var sizedMedia =
                        from m in bestMedia
                        let x = AdHandler.AdHost.VideoArea.ActualHeight - m.MediaFile.Height
                        let y = AdHandler.AdHost.VideoArea.ActualWidth - m.MediaFile.Width
                        let delta = x + y
                        orderby delta
                        select new { Media = m, DeltaX = x, DeltaY = y };

                    // try to get the one with the closest size but both dimensions are within the current size
                    var selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 && sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size where only one dimension is over the current size
                        selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 || sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size
                        selectedMedia = sizedMedia.Select(sm => sm.Media).LastOrDefault();

                    // see if there were any bitrates, if not grab which ever one was first
                    if (selectedMedia == null)
                        selectedMedia = bestMedia.First();

                    //finally, get the ad player
                    adSource = selectedMedia.AdSource;
                    adPlayer = selectedMedia.VpaidFactory.GetVpaidPlayer(adSource, adTarget);

                    if (adPlayer == null)
                    {
                        //Log.Output(OutputType.Error, "Error - cannot find player to support video ad content. ");
                        // this should never happen and is the result of a bad VPaid plugin.
                        throw new Exception("VpaidFactory agreed to accept AdSource and then returned null during call to GetVPaidPlugin.");
                    }
                    // handshake with the ad player to make sure the version of VPAID is OK
                    if (adPlayer == null || !adHandler.VpaidController.Handshake(adPlayer))
                    {
                        // the version is no good, remove the factory from the list and try again.
                        vPaidFactories.Remove(selectedMedia.VpaidFactory);
                        if (!vPaidFactories.Any())
                        {
                            return null;
                        }
                        adPlayer = null;
                    }
                }
                else
                {
                    return null;
                }
            } while (adPlayer == null);

            if (addToTarget)
            {
                //put video in target
                if (!adTarget.AddChild(adPlayer))
                {
                    return null;
                }
            }

            return new ActiveCreative(adPlayer, adSource, adTarget);
        }
        public ActiveCreative GetLinearCreative(VASTADInLineCreativeLinear linear, IAdTarget adTarget, VASTADInLine ad, params VASTADWrapper[] wrappers)
        {
            IVpaid          adPlayer;
            ICreativeSource adSource;
            var             vPaidFactories = VastAdHandler.GetVpaidFactories().ToList();

            do
            {
                // get a list of all eligible media files
                var mediaAdSources = linear.MediaFiles.ToDictionary(m => m, m => new LinearSource(ad, m, linear, wrappers));

                var rankedMedia =
                    (from mediaAdSource in mediaAdSources
                     let vPaidFactoryAndPriority = vPaidFactories.ToDictionary(f => f, f => f.CheckSupport(mediaAdSource.Value, adTarget))
                                                   where vPaidFactoryAndPriority.Values.Any(v => v > PriorityCriteriaEnum.NotSupported)
                                                   let BestVpaidFactoryAndPriority = vPaidFactoryAndPriority.OrderByDescending(kvp => kvp.Value).First()
                                                                                     let rank = BestVpaidFactoryAndPriority.Value
                                                                                                orderby rank descending
                                                                                                select new
                {
                    MediaFile = mediaAdSource.Key,
                    AdSource = mediaAdSource.Value,
                    VpaidFactory = BestVpaidFactoryAndPriority.Key,
                    Rank = rank,
                }).ToList();

                if (rankedMedia.Any())
                {
                    // get all media with the best rankings
                    var topRank   = rankedMedia.First().Rank;
                    var bestMedia = rankedMedia.Where(m => m.Rank == topRank);

                    // favor adaptive media
                    var adaptiveMedia = bestMedia.Where(m => m.MediaFile.delivery == VASTADInLineCreativeLinearMediaFileDelivery.streaming);
                    if (adaptiveMedia.Any())
                    {
                        bestMedia = adaptiveMedia;
                    }

                    double targetBitrateKbps = (double)VastAdHandler.AdHost.PlaybackBitrate / 1024;
                    if (targetBitrateKbps == 0.0)
                    {
                        // progressive videos won't have a bitrate. Therefore, target based on the one in the middle
                        targetBitrateKbps = rankedMedia.Where(m => m.MediaFile.bitrate.ToInt64().HasValue).Average(m => m.MediaFile.bitrate.ToInt64().Value);
                    }

                    // get the media with the closest bitrate
                    var bitrateMedia = bestMedia
                                       .Where(m => m.MediaFile.bitrate.ToInt64().HasValue)
                                       .GroupBy(m => Math.Abs(m.MediaFile.bitrate.ToInt64().Value))
                                       .OrderBy(m => m.Key <= MaxBitrateKbps ? 0 : m.Key - MaxBitrateKbps)
                                       .ThenBy(m => Math.Abs(m.Key - targetBitrateKbps))
                                       .FirstOrDefault();
                    if (bitrateMedia != null && bitrateMedia.Any())
                    {
                        bestMedia = bitrateMedia;
                    }

                    //// get the media with the closest bitrate
                    //var selectedMedia = bestMedia
                    //    .Where(m => !string.IsNullOrEmpty(m.MediaFile.bitrate))
                    //    .OrderBy(m => Math.Abs(long.Parse(m.MediaFile.bitrate) - VastAdHandler.AdHost.PlaybackBitrate))
                    //    .FirstOrDefault();

                    // get the media with the closest size
                    var sizedMedia =
                        from m in bestMedia
                        where m.MediaFile.height.ToInt64().HasValue&& m.MediaFile.width.ToInt64().HasValue
                        let x                                                     = VastAdHandler.AdHost.VideoArea.ActualHeight - m.MediaFile.height.ToInt64().Value
                                                    let y                         = VastAdHandler.AdHost.VideoArea.ActualWidth - m.MediaFile.width.ToInt64().Value
                                                                        let delta = x + y
                                                                                    orderby delta
                                                                                    select new { Media = m, DeltaX = x, DeltaY = y };

                    // try to get the one with the closest size but both dimensions are within the current size
                    var selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 && sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size where only one dimension is over the current size
                    {
                        selectedMedia = sizedMedia.Where(sm => sm.DeltaX >= 0 || sm.DeltaY >= 0).Select(sm => sm.Media).FirstOrDefault();
                    }
                    if (selectedMedia == null) // couldn't find one, instead get one with the closest size
                    {
                        selectedMedia = sizedMedia.Select(sm => sm.Media).LastOrDefault();
                    }

                    // see if there were any bitrates, if not grab which ever one was first in the VAST file
                    if (selectedMedia == null)
                    {
                        selectedMedia = bestMedia.First();
                    }

                    //finally, get the ad player
                    adSource = selectedMedia.AdSource;
                    adPlayer = selectedMedia.VpaidFactory.GetVpaidPlayer(adSource, adTarget);

                    if (adPlayer == null)
                    {
                        //Log.Output(OutputType.Error, "Error - cannot find player to support video ad content. ");
                        // this should never happen and is the result of a bad VPaid plugin.
                        throw new Exception("VpaidFactory agreed to accept AdSource and then returned null during call to GetVPaidPlugin.");
                    }
                    // handshake with the ad player to make sure the version of VAST is OK
                    if (adPlayer == null || !vastAdHandler.VpaidController.Handshake(adPlayer))
                    {
                        // the version is no good, remove the factory from the list and try again.
                        vPaidFactories.Remove(selectedMedia.VpaidFactory);
                        if (!vPaidFactories.Any())
                        {
                            return(null);
                        }
                        adPlayer = null;
                    }
                }
                else
                {
                    return(null);
                }
            } while (adPlayer == null);

            //put video in target
            if (!adTarget.AddChild(adPlayer))
            {
                return(null);
            }

            return(new ActiveCreative(adPlayer, adSource, adTarget));
        }