/// <summary>
        /// Produces a code minifiction of CSS assets by using Clean-css
        /// </summary>
        /// <param name="assets">Set of CSS assets</param>
        /// <returns>Set of CSS assets with minified text content</returns>
        public IList <IAsset> Minify(IList <IAsset> assets)
        {
            if (assets == null)
            {
                throw new ArgumentNullException(
                          nameof(assets),
                          string.Format(CoreStrings.Common_ArgumentIsNull, nameof(assets))
                          );
            }

            if (assets.Count == 0)
            {
                return(assets);
            }

            var assetsToProcessing = assets.Where(a => a.IsStylesheet && !a.Minified).ToList();

            if (assetsToProcessing.Count == 0)
            {
                return(assets);
            }

            CleaningOptions options = CreateCleaningOptions();

            using (var cssCleaner = new CssCleaner(_createJsEngineInstance, options))
            {
                foreach (var asset in assetsToProcessing)
                {
                    InnerMinify(asset, cssCleaner);
                }
            }

            return(assets);
        }
        /// <summary>
        /// Creates a cleaning options
        /// </summary>
        /// <returns>Cleaning options</returns>
        private CleaningOptions CreateCleaningOptions()
        {
            var options = new CleaningOptions
            {
                Compatibility             = Compatibility,
                FormattingOptions         = FormattingOptions,
                Level                     = Level,
                Level1OptimizationOptions = Level1OptimizationOptions,
                Level2OptimizationOptions = Level2OptimizationOptions,
                Severity                  = Severity
            };

            return(options);
        }
        /// <summary>
        /// Produces a code minifiction of CSS asset by using Clean-css
        /// </summary>
        /// <param name="asset">CSS asset</param>
        /// <returns>CSS asset with minified text content</returns>
        public IAsset Minify(IAsset asset)
        {
            if (asset == null)
            {
                throw new ArgumentException(CoreStrings.Common_ValueIsEmpty, "asset");
            }

            if (asset.Minified)
            {
                return(asset);
            }

            CleaningOptions options = CreateCleaningOptions();

            using (var cssCleaner = new CssCleaner(_createJsEngineInstance, options))
            {
                InnerMinify(asset, cssCleaner);
            }

            return(asset);
        }
        /// <summary>
        /// Produces a code minifiction of CSS asset by using Clean-css
        /// </summary>
        /// <param name="asset">CSS asset</param>
        /// <returns>CSS asset with minified text content</returns>
        public IAsset Minify(IAsset asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(
                          nameof(asset),
                          string.Format(CoreStrings.Common_ArgumentIsNull, nameof(asset))
                          );
            }

            if (asset.Minified)
            {
                return(asset);
            }

            CleaningOptions options = CreateCleaningOptions();

            using (var cssCleaner = new CssCleaner(_createJsEngineInstance, options))
            {
                InnerMinify(asset, cssCleaner);
            }

            return(asset);
        }
		/// <summary>
		/// Creates a cleaning options
		/// </summary>
		/// <returns>Cleaning options</returns>
		private CleaningOptions CreateCleaningOptions()
		{
			var options = new CleaningOptions
			{
				Advanced = Advanced,
				AggressiveMerging = AggressiveMerging,
				Compatibility = Compatibility,
				KeepBreaks = KeepBreaks,
				KeepSpecialComments = KeepSpecialComments,
				MediaMerging = MediaMerging,
				Restructuring = Restructuring,
				RoundingPrecision = RoundingPrecision,
				SemanticMerging = SemanticMerging,
				ShorthandCompacting = ShorthandCompacting,
				Severity = Severity
			};

			return options;
		}
		/// <summary>
		/// Constructs a instance of CSS-cleaner
		/// </summary>
		/// <param name="createJsEngineInstance">Delegate that creates an instance of JavaScript engine</param>
		/// <param name="defaultOptions">Default cleaning options</param>
		public CssCleaner(Func<IJsEngine> createJsEngineInstance, CleaningOptions defaultOptions)
		{
			_jsEngine = createJsEngineInstance();
			_defaultOptions = defaultOptions ?? new CleaningOptions();
			_defaultOptionsString = ConvertCleaningOptionsToJson(_defaultOptions).ToString();
		}
		/// <summary>
		/// Converts a cleaning options to JSON
		/// </summary>
		/// <param name="options">Cleaning options</param>
		/// <returns>Cleaning options in JSON format</returns>
		private static JObject ConvertCleaningOptionsToJson(CleaningOptions options)
		{
			var optionsJson = new JObject(
				new JProperty("advanced", options.Advanced),
				new JProperty("aggressiveMerging", options.AggressiveMerging),
				new JProperty("compatibility", options.Compatibility),
				new JProperty("keepBreaks", options.KeepBreaks),
				new JProperty("keepSpecialComments",
					ConvertSpecialCommentsModeEnumValueToCode(options.KeepSpecialComments)),
				new JProperty("mediaMerging", options.MediaMerging),
				new JProperty("restructuring", options.Restructuring),
				new JProperty("roundingPrecision", options.RoundingPrecision),
				new JProperty("semanticMerging", options.SemanticMerging),
				new JProperty("shorthandCompacting", options.ShorthandCompacting)
			);

			return optionsJson;
		}
		/// <summary>
		/// "Cleans" CSS-code by using Clean-css
		/// </summary>
		/// <param name="content">Text content of CSS-asset</param>
		/// <param name="path">Path to CSS-file</param>
		/// <param name="options">Cleaning options</param>
		/// <returns>Minified text content of CSS-asset</returns>
		public string Clean(string content, string path, CleaningOptions options = null)
		{
			string newContent;
			CleaningOptions currentOptions;
			string currentOptionsString;

			if (options != null)
			{
				currentOptions = options;
				currentOptionsString = ConvertCleaningOptionsToJson(options).ToString();
			}
			else
			{
				currentOptions = _defaultOptions;
				currentOptionsString = _defaultOptionsString;
			}

			lock (_cleaningSynchronizer)
			{
				Initialize();

				try
				{
					var result = _jsEngine.Evaluate<string>(
						string.Format(CLEANING_FUNCTION_CALL_TEMPLATE,
							JsonConvert.SerializeObject(content), currentOptionsString));

					var json = JObject.Parse(result);

					var errors = json["errors"] != null ? json["errors"] as JArray : null;
					if (errors != null && errors.Count > 0)
					{
						throw new CssCleaningException(FormatErrorDetails(errors[0].Value<string>(), true,
							path));
					}

					if (currentOptions.Severity > 0)
					{
						var warnings = json["warnings"] != null ? json["warnings"] as JArray : null;
						if (warnings != null && warnings.Count > 0)
						{
							throw new CssCleaningException(FormatErrorDetails(warnings[0].Value<string>(),
								false, path));
						}
					}

					newContent = json.Value<string>("minifiedCode");
				}
				catch (JsRuntimeException e)
				{
					throw new CssCleaningException(JsRuntimeErrorHelpers.Format(e));
				}
			}

			return newContent;
		}