internal MinifyCssResult Process(ContentItem contentItem, FileHasherActivity imageHasher = null)
        {
            if (imageHasher != null)
            {
                this.availableSourceImages = this.context.GetAvailableFiles(this.context.Configuration.SourceDirectory, this.ImageDirectories, this.ImageExtensions, FileTypes.Image);
            }

            var cssContent = contentItem.Content;

            var minifiedContentItems     = new BlockingCollection <ContentItem>();
            var hashedImageContentItems  = new BlockingCollection <ContentItem>();
            var spritedImageContentItems = new BlockingCollection <ContentItem>();
            var mergedResources          = ResourcePivotActivity.GetUsedGroupedResources(cssContent, this.MergedResources);

            var dpiValues = this.Dpi;

            if (dpiValues == null || !dpiValues.Any())
            {
                dpiValues = new HashSet <float>(new[] { 1f });
            }

            var pivots = GetMinifyCssPivots(contentItem, dpiValues, mergedResources, this.DpiResources).ToArray();

            var nonIgnoredPivots = pivots.Where(p => !this.context.TemporaryIgnore(p.NewContentResourcePivotKeys)).ToArray();

            var parsedStylesheetNode = CssParser.Parse(this.context, cssContent, false);

            this.context.ParallelForEach(
                item => new[] { SectionIdParts.MinifyCssActivity },
                nonIgnoredPivots,
                (threadContext, pivot, parallelLoopState) =>
            {
                ContentItem minifiedContentItem = null;
                var resourceContentItem         = ContentItem.FromContent(contentItem.Content, pivot.NewContentResourcePivotKeys);
                var result = threadContext
                             .SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.Process)
                             .MakeCachable(resourceContentItem, this.GetVarBySettings(imageHasher, pivot.NewContentResourcePivotKeys, pivot.MergedResource))
                             .RestoreFromCacheAction(cacheSection =>
                {
                    minifiedContentItem = cacheSection.GetCachedContentItem(CacheFileCategories.MinifiedCssResult, contentItem.RelativeContentPath, contentItem.AbsoluteDiskPath, pivot.NewContentResourcePivotKeys);
                    hashedImageContentItems.AddRange(cacheSection.GetCachedContentItems(CacheFileCategories.HashedImage));
                    spritedImageContentItems.AddRange(cacheSection.GetCachedContentItems(CacheFileCategories.HashedSpriteImage));

                    if (minifiedContentItem == null)
                    {
                        context.Log.Error("Css minify cache result is null");
                        return(false);
                    }

                    if (spritedImageContentItems.Any(hi => hi == null))
                    {
                        context.Log.Error("Sprited image cache result is null");
                        return(false);
                    }

                    if (hashedImageContentItems.Any(hi => hi == null))
                    {
                        context.Log.Error("Hashed image cache result is null");
                        return(false);
                    }

                    return(true);
                })
                             .Execute(cacheSection =>
                {
                    try
                    {
                        // Apply all configured visitors, including, validating, optimizing, minifying and spriting.

                        // Applying of resources
                        var stylesheetNode = ApplyResources(parsedStylesheetNode, pivot.MergedResource, threadContext) as StyleSheetNode;

                        // Validation
                        stylesheetNode = this.ApplyValidation(stylesheetNode, threadContext) as StyleSheetNode;

                        // Optimization
                        stylesheetNode = this.ApplyOptimization(stylesheetNode, threadContext) as StyleSheetNode;

                        // Spriting
                        stylesheetNode = this.ApplySpriting(stylesheetNode, pivot.Dpi, spritedImageContentItems, threadContext) as StyleSheetNode;

                        // Output css as string
                        var processedCssContent = threadContext.SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.PrintCss).Execute(() =>
                                                                                                                                                   this.ShouldMinify ? stylesheetNode.MinifyPrint() : stylesheetNode.PrettyPrint());

                        // TODO: Hash the images on the styielsheetnode not on the css result.
                        // Hash images on the result css
                        if (imageHasher != null)
                        {
                            var hashResult      = HashImages(processedCssContent, imageHasher, cacheSection, threadContext, this.availableSourceImages, this.MissingImageUrl);
                            processedCssContent = hashResult.Item1;
                            hashedImageContentItems.AddRange(hashResult.Item2);
                        }

                        minifiedContentItem = ContentItem.FromContent(processedCssContent, this.DestinationFile, null, pivot.NewContentResourcePivotKeys);
                        cacheSection.AddResult(minifiedContentItem, CacheFileCategories.MinifiedCssResult);
                    }
                    catch (Exception ex)
                    {
                        context.Log.Error(ex, ex.ToString());
                        return(false);
                    }

                    return(true);
                });

                Safe.Lock(minifiedContentItems, () => minifiedContentItems.Add(minifiedContentItem));

                if (!result)
                {
                    context.Log.Error("An errror occurred while minifying '{0}' with resources '{1}'".InvariantFormat(contentItem.RelativeContentPath, pivot));
                }

                return(result);
            });

            return(new MinifyCssResult(
                       minifiedContentItems,
                       spritedImageContentItems.DistinctBy(hi => hi.RelativeContentPath).ToArray(),
                       hashedImageContentItems.DistinctBy(hi => hi.RelativeContentPath).ToArray()));
        }