internal static bool TryGetBackgroundDeclaration(this IEnumerable <DeclarationNode> declarationAstNodes, AstNode parentAstNode, out Background backgroundNode, out BackgroundImage backgroundImageNode, out BackgroundPosition backgroundPositionNode, out DeclarationNode backgroundSize, List <string> imageReferencesInInvalidDeclarations, HashSet <string> imageReferencesToIgnore, ImageAssemblyAnalysisLog imageAssemblyAnalysisLog, string outputUnit, double outputUnitFactor, bool ignoreImagesWithNonDefaultBackgroundSize = false)
        {
            // Initialize the nodes to null
            backgroundNode         = null;
            backgroundImageNode    = null;
            backgroundPositionNode = null;
            backgroundSize         = null;

            // With CSS3 multiple urls can be present in a single rule, this is not yet supported
            // background: url(flower.png), url(ball.png), url(grass.png) no-repeat;
            if (BackgroundImage.HasMultipleUrls(parentAstNode.MinifyPrint()))
            {
                imageAssemblyAnalysisLog.SafeAdd(parentAstNode, null, FailureReason.MultipleUrls);
                return(false);
            }

            // This will check if the selector hash -wg-spriting: ignore. If it does we will ignore the sprite.
            var webGreaseSpritingProperty = declarationAstNodes.FirstOrDefault(d => d.Property == "-wg-spriting");

            if (webGreaseSpritingProperty != null && webGreaseSpritingProperty.ExprNode.TermNode.StringBasedValue == "ignore")
            {
                imageAssemblyAnalysisLog.SafeAdd(parentAstNode, null, FailureReason.SpritingIgnore);
                return(false);
            }

            // The list of declarations should not have the duplicate declaration
            // properties. Validate and get the dictionary of declarations.
            var declarationProperties = declarationAstNodes.LoadDeclarationPropertiesDictionary();

            // The selector design is inefficient if the shorthand notation and long name is defined
            // in a scope of ruleset declaration, media ruleset declaration or page declaration. This
            // would be a great feature to add to Optimization visitor but would require a full table
            // scanning which is not yet implemented.
            // Per MSN CSS standards, the practice of defining the shorthand notation and long name
            // in scope of same selector is not allowed.
            DeclarationNode declarationAstNode;

            if (declarationProperties.TryGetValue(ImageAssembleConstants.Background, out declarationAstNode))
            {
                // There should not be any short and long notation simultaneosuly used in these set of declarations.
                // For example: Such a list of declarations end up in inefficient CSS.
                // #selector
                // {
                // background:url(foo.gif);
                // background-image:url(../../i/D5/DF5D9B4EFD5CFF9122942A67A1EEC5.gif);
                // background-position:500px 500px;
                // background-repeat:no-repeat
                // }
                // By design, we are not computing cascade here.
                // TODO: RTUIT: Add support to override some of these with extra values depending on the order, or use optimization to do this when merging styles.
                if (declarationProperties.ContainsKey(ImageAssembleConstants.BackgroundRepeat) ||
                    declarationProperties.ContainsKey(ImageAssembleConstants.BackgroundImage) ||
                    declarationProperties.ContainsKey(ImageAssembleConstants.BackgroundPosition))
                {
                    throw new ImageAssembleException(CssStrings.DuplicateBackgroundFormatError);
                }

                // Load the model for the "background" declaration
                var parsedBackground = new Background(declarationAstNode, outputUnit, outputUnitFactor);

                ////
                //// The url should be present
                ////
                bool shouldIgnore;
                if (!parsedBackground.BackgroundImage.VerifyBackgroundUrl(parentAstNode, imageReferencesToIgnore, imageAssemblyAnalysisLog, out shouldIgnore) ||
                    shouldIgnore)
                {
                    return(false);
                }

                ////
                //// The "no-repeat" term should be explicitly configured on the "background" declaration
                ////
                if (!parsedBackground.BackgroundRepeat.VerifyBackgroundNoRepeat())
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackground.Url, FailureReason.BackgroundRepeatInvalid);
                    UpdateFailedUrlsList(parsedBackground.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                ////
                //// The background position should only be empty, x = any value and y = 0, top or px
                ////
                if (!parsedBackground.BackgroundPosition.IsVerticalSpriteCandidate())
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackground.Url, FailureReason.IncorrectPosition);
                    UpdateFailedUrlsList(parsedBackground.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                //// Try to get the background size, returns false if we want to ignore images with background sizes and the background size is set to a non-default value.
                if (!TryGetBackgroundSize(ignoreImagesWithNonDefaultBackgroundSize, declarationProperties, out backgroundSize))
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackground.Url, FailureReason.BackgroundSizeIsSetToNonDefaultValue);
                    UpdateFailedUrlsList(parsedBackground.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                backgroundNode = parsedBackground;
                imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackground.Url);

                //// SUCCESS - This is the candidate!
                return(true);
            }

            // Now there should be declaration for "background-image" or "background-repeat" or both
            if (declarationProperties.TryGetValue(ImageAssembleConstants.BackgroundImage, out declarationAstNode))
            {
                // Load the property model for the "background-image" declaration
                var parsedBackgroundImage = new BackgroundImage(declarationAstNode);

                ////
                //// The url should be present
                ////
                bool shouldIgnore;
                if (!parsedBackgroundImage.VerifyBackgroundUrl(parentAstNode, imageReferencesToIgnore, imageAssemblyAnalysisLog, out shouldIgnore) ||
                    shouldIgnore)
                {
                    return(false);
                }

                ////
                //// There is a "background-repeat" declaration found
                ////
                DeclarationNode backgroundRepeat;
                if (!declarationProperties.TryGetValue(ImageAssembleConstants.BackgroundRepeat, out backgroundRepeat))
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackgroundImage.Url, FailureReason.NoRepeat);
                    UpdateFailedUrlsList(parsedBackgroundImage.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                ////
                //// Now make sure that "background-repeat" is "no-repeat"
                ////
                if (!new BackgroundRepeat(backgroundRepeat).VerifyBackgroundNoRepeat())
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackgroundImage.Url, FailureReason.BackgroundRepeatInvalid);
                    UpdateFailedUrlsList(parsedBackgroundImage.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                //// Try to get the background size, returns false if we want to ignore images with background sizes and the background size is set to a non-default value.
                if (!TryGetBackgroundSize(ignoreImagesWithNonDefaultBackgroundSize, declarationProperties, out backgroundSize))
                {
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackgroundImage.Url, FailureReason.BackgroundSizeIsSetToNonDefaultValue);
                    UpdateFailedUrlsList(parsedBackgroundImage.Url, imageReferencesInInvalidDeclarations);
                    return(false);
                }

                ////
                //// The background position should only be empty, x = any value and y = 0, top or px
                ////
                DeclarationNode backgroundPosition;
                if (declarationProperties.TryGetValue(ImageAssembleConstants.BackgroundPosition, out backgroundPosition))
                {
                    // Now if there is a "background-position" declaration (optional), lets make
                    // it should only be empty, px or left/top or right/px
                    var parsedBackgroundPosition = new BackgroundPosition(backgroundPosition, outputUnit, outputUnitFactor);

                    if (!parsedBackgroundPosition.IsVerticalSpriteCandidate())
                    {
                        imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackgroundImage.Url, FailureReason.IncorrectPosition);
                        UpdateFailedUrlsList(parsedBackgroundImage.Url, imageReferencesInInvalidDeclarations);
                        return(false);
                    }

                    backgroundImageNode    = parsedBackgroundImage;
                    backgroundPositionNode = parsedBackgroundPosition;
                    imageAssemblyAnalysisLog.SafeAdd(parentAstNode, parsedBackgroundImage.Url);

                    //// SUCCESS - This is the candidate!
                    return(true);
                }

                backgroundImageNode = parsedBackgroundImage;
                imageAssemblyAnalysisLog.SafeAdd(parentAstNode, backgroundImageNode.Url);

                //// SUCCESS - This is the candidate!
                return(true);
            }

            return(false);
        }