/// <inheritdoc />
        protected virtual async void ShowIcon(Microsoft.Media.Advertising.Icon icon, StaticResource staticResource, CancellationTokenSource cts)
        {
            if (icon.Offset.HasValue)
            {
                try
                {
#if SILVERLIGHT && !WINDOWS_PHONE || WINDOWS_PHONE7
                    await TaskEx.Delay((int)icon.Offset.Value.TotalMilliseconds, cts.Token);
#else
                    await Task.Delay((int)icon.Offset.Value.TotalMilliseconds, cts.Token);
#endif
                }
                catch (OperationCanceledException) { /* swallow */ }
            }

            if (!cts.IsCancellationRequested)
            {
                var iconHost = new HyperlinkButton();
                iconHost.NavigateUri = icon.ClickThrough;

                double topMargin  = 0;
                double leftMargin = 0;
                if (icon.Width.HasValue)
                {
                    iconHost.Width = icon.Width.Value;
                }
                if (icon.Height.HasValue)
                {
                    iconHost.Height = icon.Height.Value;
                }
                switch (icon.XPosition)
                {
                case "left":
                    iconHost.HorizontalAlignment = HorizontalAlignment.Left;
                    break;

                case "right":
                    iconHost.HorizontalAlignment = HorizontalAlignment.Right;
                    break;

                default:
                    iconHost.HorizontalAlignment = HorizontalAlignment.Left;
                    int xPositionValue;
                    if (int.TryParse(icon.XPosition, out xPositionValue))
                    {
                        leftMargin = xPositionValue;
                    }
                    break;
                }
                switch (icon.YPosition)
                {
                case "top":
                    iconHost.VerticalAlignment = VerticalAlignment.Top;
                    break;

                case "bottom":
                    iconHost.VerticalAlignment = VerticalAlignment.Bottom;
                    break;

                default:
                    iconHost.VerticalAlignment = VerticalAlignment.Top;
                    int yPositionValue;
                    if (int.TryParse(icon.YPosition, out yPositionValue))
                    {
                        topMargin = yPositionValue;
                    }
                    break;
                }
                iconHost.Margin = new Thickness(leftMargin, topMargin, 0, 0);

                var iconElement = new Image();
                iconElement.Stretch = Stretch.Fill;
                iconElement.Source  = new BitmapImage(staticResource.Value);
                iconHost.Content    = iconElement;

                //TODO: avoid visually overlaping icons

                iconHost.Tag    = icon;
                iconElement.Tag = icon;

                iconHost.Click          += iconHost_Click;
                iconElement.ImageOpened += iconElement_ImageOpened;
                AdContainer.Children.Add(iconHost);

                try
                {
                    if (icon.Duration.HasValue)
                    {
#if SILVERLIGHT && !WINDOWS_PHONE || WINDOWS_PHONE7
                        await TaskEx.Delay((int)icon.Duration.Value.TotalMilliseconds, cts.Token);
#else
                        await Task.Delay((int)icon.Duration.Value.TotalMilliseconds, cts.Token);
#endif
                    }
                    else
                    {
                        await cts.Token.AsTask();
                    }
                }
                catch (OperationCanceledException) { /* swallow */ }
                finally
                {
                    AdContainer.Children.Remove(iconHost);
                    iconHost.Click          -= iconHost_Click;
                    iconElement.ImageOpened -= iconElement_ImageOpened;
                }
            }
        }
        private static void LoadCreatives(XElement adElement, Ad ad)
        {
            var vastCreatives = adElement.Element("Creatives");
            if (vastCreatives != null)
            {
                foreach (var vastCreative in vastCreatives.Elements("Creative"))
                {
                    var vastItem = vastCreative.Elements().FirstOrDefault();
                    if (vastItem != null)
                    {
                        ICreative creative = null;
                        switch (vastItem.Name.LocalName)
                        {
                            case "Linear":
                                var vastLinear = vastItem;
                                var linearCreative = new CreativeLinear();
                                creative = linearCreative;

                                foreach (var trackingEvent in GetTrackingEvents(vastLinear))
                                    linearCreative.TrackingEvents.Add(trackingEvent);

                                if (vastLinear.Elements("AdParameters").Any())
                                {
                                    var xmlEncoded = (bool?)vastLinear.Element("AdParameters").Attribute("xmlEncoded") ?? false;
                                    linearCreative.AdParameters = xmlEncoded ? XmlDecode((string)vastLinear.Element("AdParameters")) : (string)vastLinear.Element("AdParameters");
                                }

                                LoadVideoClicks(vastLinear, linearCreative);

                                if (vastLinear.Elements("CreativeExtensions").Any())
                                {
                                    foreach (var vastExtension in vastLinear.Element("CreativeExtensions").Elements("CreativeExtension"))
                                    {
                                        linearCreative.Extensions.Add(new Extension()); // TODO
                                    }
                                }

                                linearCreative.Duration = ToNullableTimeSpan((string)vastLinear.Element("Duration"));
                                linearCreative.SkipOffset = FlexibleOffset.Parse((string)vastLinear.Attribute("skipoffset"));

                                var vastIcons = vastLinear.Element("Icons");
                                if (vastIcons != null)
                                {
                                    foreach (var vastIcon in vastIcons.Elements("Icon"))
                                    {
                                        var icon = new Icon();

                                        if (vastIcon.Elements("IconClicks").Any())
                                        {
                                            var iconClicks = vastIcon.Element("IconClicks");

                                            icon.ClickThrough = GetUriValue(iconClicks.Element("IconClickThrough"));

                                            foreach (var clickTracking in iconClicks.Elements("IconClickTracking"))
                                            {
                                                icon.ClickTracking.Add((string)clickTracking);
                                            }
                                        }

                                        icon.ApiFramework = (string)vastIcon.Attribute("apiFramework") ?? string.Empty;
                                        icon.Duration = ToNullableTimeSpan((string)vastIcon.Attribute("duration")) ?? new TimeSpan?();
                                        icon.Height = (int?)vastIcon.Attribute("height");
                                        icon.Width = (int?)vastIcon.Attribute("width");
                                        icon.Offset = ToNullableTimeSpan((string)vastIcon.Attribute("offset")) ?? new TimeSpan?();
                                        icon.Program = (string)vastIcon.Attribute("program") ?? string.Empty;
                                        icon.XPosition = (string)vastIcon.Attribute("xPosition") ?? string.Empty;
                                        icon.YPosition = (string)vastIcon.Attribute("yPosition") ?? string.Empty;
                                        icon.Item = GetResources(vastIcon).FirstOrDefault();
                                        foreach (var viewTrackingUrl in vastIcon.Elements("IconViewTracking"))
                                        {
                                            icon.ViewTracking.Add((string)viewTrackingUrl);
                                        }
                                        linearCreative.Icons.Add(icon);
                                    }
                                }

                                if (vastLinear.Elements("MediaFiles").Any())
                                {
                                    foreach (var vastMedia in vastLinear.Element("MediaFiles").Elements("MediaFile"))
                                    {
                                        var mediaFile = new MediaFile();
                                        mediaFile.ApiFramework = (string)vastMedia.Attribute("apiFramework") ?? string.Empty;
                                        mediaFile.Bitrate = ToNullableLong((string)vastMedia.Attribute("bitrate"));
                                        mediaFile.Codec = (string)vastMedia.Attribute("codec") ?? string.Empty;
                                        mediaFile.Delivery = (MediaFileDelivery)Enum.Parse(typeof(MediaFileDelivery), (string)vastMedia.Attribute("delivery"), true);
                                        mediaFile.Height = (int?)vastMedia.Attribute("height") ?? 0;
                                        mediaFile.Width = (int?)vastMedia.Attribute("width") ?? 0;
                                        mediaFile.Id = (string)vastMedia.Attribute("id");
                                        mediaFile.MaintainAspectRatio = (bool?)vastMedia.Attribute("maintainAspectRatio") ?? false;
                                        mediaFile.MaxBitrate = (long?)vastMedia.Attribute("maxBitrate") ?? 0;
                                        mediaFile.MinBitrate = (long?)vastMedia.Attribute("minBitrate") ?? 0;
                                        mediaFile.Scalable = (bool?)vastMedia.Attribute("scalable") ?? false;
                                        mediaFile.Type = (string)vastMedia.Attribute("type");
                                        mediaFile.Value = GetUriValue(vastMedia);
                                        linearCreative.MediaFiles.Add(mediaFile);
                                    }
                                }
                                break;
                            case "CompanionAds":
                                var vastCompanions = vastItem;
                                creative = LoadCompanions(vastCompanions);
                                break;
                            case "NonLinearAds":
                                var vastNonLinears = vastItem;
                                var nonLinearCreative = new CreativeNonLinears();
                                creative = nonLinearCreative;

                                foreach (var trackingEvent in GetTrackingEvents(vastNonLinears))
                                    nonLinearCreative.TrackingEvents.Add(trackingEvent);

                                foreach (var vastNonLinear in vastNonLinears.Elements("NonLinear"))
                                {
                                    var nonLinear = new NonLinear();

                                    if (vastNonLinear.Elements("AdParameters").Any())
                                    {
                                        var xmlEncoded = (bool?)vastNonLinear.Element("AdParameters").Attribute("xmlEncoded") ?? false;
                                        nonLinear.AdParameters = xmlEncoded ? XmlDecode((string)vastNonLinear.Element("AdParameters")) : (string)vastNonLinear.Element("AdParameters");
                                    };
                                    nonLinear.ApiFramework = (string)vastNonLinear.Attribute("apiFramework");
                                    nonLinear.ClickThrough = GetUriValue(vastNonLinear.Element("NonLinearClickThrough"));
                                    foreach (var vastTracking in vastNonLinear.Elements("NonLinearClickTracking"))
                                    {
                                        nonLinear.ClickTracking.Add((string)vastTracking);
                                    }

                                    if (vastNonLinear.Elements("CreativeExtensions").Any())
                                    {
                                        foreach (var vastExtension in vastNonLinear.Element("CreativeExtensions").Elements("CreativeExtension"))
                                        {
                                            nonLinear.Extensions.Add(new Extension()); // TODO
                                        }
                                    }
                                    nonLinear.ExpandedHeight = (int?)vastNonLinear.Attribute("expandedHeight");
                                    nonLinear.ExpandedWidth = (int?)vastNonLinear.Attribute("expandedWidth");
                                    nonLinear.Height = (int?)vastNonLinear.Attribute("height") ?? 0;
                                    nonLinear.Width = (int?)vastNonLinear.Attribute("width") ?? 0;
                                    nonLinear.MaintainAspectRatio = (bool?)vastNonLinear.Attribute("maintainAspectRatio") ?? false;
                                    nonLinear.MinSuggestedDuration = ToNullableTimeSpan((string)vastNonLinear.Attribute("minSuggestedDuration")) ?? new TimeSpan?();
                                    nonLinear.Scalable = (bool?)vastNonLinear.Attribute("scalable") ?? false;
                                    nonLinear.Item = GetResources(vastNonLinear).FirstOrDefault();
                                    nonLinearCreative.NonLinears.Add(nonLinear);
                                }
                                break;
                        }
                        if (creative != null)
                        {
                            creative.AdId = (string)vastCreative.Attribute("AdID");
                            creative.Id = (string)vastCreative.Attribute("id");
                            creative.Sequence = ToNullableInt((string)vastCreative.Attribute("sequence"));
                            ad.Creatives.Add(creative);
                        }
                    }
                }
            }
        }