/// <summary>
        /// Merge the specified style with this instance and optionally ovwerite any conflicting parameters
        /// </summary>
        /// <param name="style">Source.</param>
        /// <param name="overwriteExisting">Overwrite existing.</param>
        public void Merge(TextStyleParameters style, bool overwriteExisting)
        {
            Type t = typeof(TextStyleParameters);

            var properties = t.GetRuntimeProperties().Where(prop => prop.CanRead && prop.CanWrite);

            foreach (var prop in properties)
            {
                var sourceValue = prop.GetValue(style, null);

                if (sourceValue != null)
                {
                    var targetValue = prop.GetValue(this, null);

                    switch (prop.Name)
                    {
                    case "TextAlign":
                        if ((TextStyleAlign)sourceValue != TextStyleAlign.Left)
                        {
                            targetValue = null;
                        }
                        break;

                    case "TextDecoration":
                        if ((TextStyleDecoration)sourceValue != TextStyleDecoration.None)
                        {
                            targetValue = null;
                        }
                        break;

                    case "TextOverflow":
                        if ((TextStyleTextOverflow)sourceValue != TextStyleTextOverflow.None)
                        {
                            targetValue = null;
                        }
                        break;

                    case "TextTransform":
                        if ((TextStyleTextTransform)sourceValue != TextStyleTextTransform.None)
                        {
                            targetValue = null;
                        }
                        break;
                    }

                    if (targetValue != null && !overwriteExisting)
                    {
                        continue;
                    }

                    prop.SetValue(this, sourceValue, null);
                }
            }
        }
        /// <summary>
        /// Merges a css rule.
        /// </summary>
        /// <returns>The rule.</returns>
        /// <param name="curStyle">Target TextStyleParameters</param>
        /// <param name="css">Css value</param>
        /// <param name="clone">If set to <c>true</c> clone the style</param>
        public static TextStyleParameters MergeRule(TextStyleParameters curStyle, string css, bool clone)
        {
            var parser = new CssParser();
            var rules  = parser.ParseAll(css);

            if (rules.Count() != 1)
            {
                throw new NotSupportedException("Only a single css class may be merged at a time");
            }

            var mergedStyle = clone ? curStyle.Clone() : curStyle;

            var rule = rules.FirstOrDefault();

            if (rule != null)
            {
                ParseCSSRule(ref mergedStyle, rule);
            }

            return(mergedStyle);
        }
        /// <summary>
        /// Parses the specified CSS
        /// </summary>
        /// <param name="css">Css.</param>
        public static Dictionary <string, TextStyleParameters> Parse(string css)
        {
            var parser = new CssParser();
            var rules  = parser.ParseAll(css);

            var textStyles = new Dictionary <string, TextStyleParameters> ();

            foreach (var rule in rules)
            {
                foreach (var selector in rule.Selectors)
                {
                    // If it doesnt exist, create it
                    if (!textStyles.ContainsKey(selector))
                    {
                        textStyles [selector] = new TextStyleParameters(selector);
                    }

                    var curStyle = textStyles [selector];
                    ParseCSSRule(ref curStyle, rule);
                }
            }

            return(textStyles);
        }
        /// <summary>
        /// Parses the CSS rule.
        /// </summary>
        /// <param name="curStyle">Current style.</param>
        /// <param name="rule">Rule.</param>
        internal static void ParseCSSRule(ref TextStyleParameters curStyle, CssParserRule rule)
        {
            foreach (var declaration in rule.Declarations)
            {
                if (_textStyleProperties.ContainsKey(declaration.Property))
                {
                    var cleanedValue = declaration.Value.Replace("\"", "");
                    cleanedValue = cleanedValue.Trim();
                    var prop = _textStyleProperties [declaration.Property];
                    switch (prop.PropertyType.Name)
                    {
                    case "String":
                        curStyle.SetValue(prop.Name, cleanedValue);
                        break;

                    case "Int32":
                        int numInt;
                        if (int.TryParse(cleanedValue, out numInt))
                        {
                            curStyle.SetValue(prop.Name, numInt);
                        }
                        break;

                    case "Single":
                        cleanedValue = cleanedValue.Replace("px", "");
                        float numFloat;
                        if (float.TryParse(cleanedValue, out numFloat))
                        {
                            curStyle.SetValue(prop.Name, numFloat);
                        }
                        else
                        {
                            throw new Exception("Failed to Parse Single value " + cleanedValue);
                        }
                        break;

                    case "Single[]":
                        var parts        = cleanedValue.Split(new char [] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                        var parsedValues = new float [parts.Length];
                        for (int i = 0; i < parts.Length; i++)
                        {
                            float numArrayFloat;
                            if (float.TryParse(parts [i], out numArrayFloat))
                            {
                                parsedValues [i] = numArrayFloat;
                            }
                        }
                        curStyle.SetValue(prop.Name, parsedValues);
                        break;

                    case "TextStyleAlign":
                        curStyle.TextAlign = EnumUtils.FromDescription <TextStyleAlign> (cleanedValue);
                        break;

                    case "TextStyleDecoration":
                        curStyle.TextDecoration = EnumUtils.FromDescription <TextStyleDecoration> (cleanedValue);
                        break;

                    case "TextStyleTextTransform":
                        curStyle.TextTransform = EnumUtils.FromDescription <TextStyleTextTransform> (cleanedValue);
                        break;

                    case "TextStyleTextOverflow":
                        curStyle.TextOverflow = EnumUtils.FromDescription <TextStyleTextOverflow> (cleanedValue);
                        break;

                    case "TextStyleFontStyle":
                        curStyle.FontStyle = EnumUtils.FromDescription <TextStyleFontStyle> (cleanedValue);
                        break;

                    case "TextStyleFontWeight":
                        curStyle.FontWeight = EnumUtils.FromDescription <TextStyleFontWeight> (cleanedValue);
                        break;

                    default:
                        throw new InvalidCastException("Could not find the appropriate type " + prop.PropertyType.Name);
                    }
                }
            }
        }
        /// <summary>
        /// Parses to CSS string.
        /// </summary>
        /// <returns>The to CSS string.</returns>
        /// <param name="tagName">Tag name.</param>
        /// <param name="style">Style.</param>
        public static string ParseToCSSString(string tagName, TextStyleParameters style)
        {
            var builder = new StringBuilder();

            builder.Append(tagName + "{");

            string cast;
            var    runtimeProperties = style.GetType().GetRuntimeProperties();

            foreach (var prop in runtimeProperties)
            {
                try {
                    var value = prop.GetValue(style);

                    if (value != null)
                    {
                        string parsedValue = null;
                        switch (prop.PropertyType.Name)
                        {
                        case "String":
                            if ((value as string).StartsWith("#"))
                            {
                                parsedValue = (string)value;
                            }
                            else
                            {
                                parsedValue = "'" + value + "'";
                            }
                            break;

                        case "Single":
                            if (Convert.ToSingle(value) > float.MinValue)
                            {
                                parsedValue = Convert.ToString(value);
                                if (prop.Name == "FontSize")                                 // Dirty, I really need a list of things that can be set in pixel values
                                {
                                    parsedValue += "px";
                                }
                            }
                            break;

                        case "Int32":
                            if (Convert.ToInt32(value) > int.MinValue)
                            {
                                parsedValue = Convert.ToString(value);
                            }
                            break;

                        case "Single[]":
                            parsedValue = Convert.ToString(value);
                            break;

                        case "TextStyleAlign":
                        case "TextStyleDecoration":
                        case "TextStyleTextTransform":
                        case "TextStyleTextOverflow":
                            cast = Convert.ToString(value);
                            if (cast != "None")
                            {
                                parsedValue = cast.ToLower();
                            }
                            break;

                        case "TextStyleFontStyle":
                        case "TextStyleFontWeight":
                            cast = Convert.ToString(value);
                            if (cast != "Normal")
                            {
                                parsedValue = cast.ToLower();
                            }
                            break;

                        default:
                            throw new InvalidCastException("Could not find the appropriate type " + prop.PropertyType.Name);
                        }

                        var attributes = (CssAttribute[])prop.GetCustomAttributes(
                            typeof(CssAttribute), false);

                        if (attributes.Length > 0 && parsedValue != null)
                        {
                            builder.Append(attributes [0].Name + ":" + parsedValue + ";");
                        }
                    }
                } catch (Exception ex) {
                    throw ex;
                }
            }

            builder.Append("}");

            return(builder.ToString());
        }