using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml;
using System.Drawing;

namespace OfficeOpenXml.Style.Dxf
{
    public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting>
    {
        XmlHelperInstance _helper;
        internal ExcelDxfStyleConditionalFormatting(XmlNamespaceManager nameSpaceManager, XmlNode topNode, ExcelStyles styles) : base(styles)
        {
            NumberFormat = new ExcelDxfNumberFormat(_styles);
            Font = new ExcelDxfFontBase(_styles);
            Border = new ExcelDxfBorderBase(_styles);
            Fill = new ExcelDxfFill(_styles);
            if (topNode != null)
            {
                _helper = new XmlHelperInstance(nameSpaceManager, topNode);
                NumberFormat.NumFmtID = _helper.GetXmlNodeInt("d:numFmt/@numFmtId");
                NumberFormat.Format = _helper.GetXmlNodeString("d:numFmt/@formatCode"); 
                if (NumberFormat.NumFmtID < 164 && string.IsNullOrEmpty(NumberFormat.Format))
                {
                    NumberFormat.Format = ExcelNumberFormat.GetFromBuildInFromID(NumberFormat.NumFmtID);
                }

                Font.Bold = _helper.GetXmlNodeBoolNullable("d:font/d:b/@val");
                Font.Italic = _helper.GetXmlNodeBoolNullable("d:font/d:i/@val");
                Font.Strike = _helper.GetXmlNodeBoolNullable("d:font/d:strike");
                Font.Underline = GetUnderLineEnum(_helper.GetXmlNodeString("d:font/d:u/@val"));
                Font.Color = GetColor(_helper, "d:font/d:color");

                Border.Left = GetBorderItem(_helper, "d:border/d:left");
                Border.Right = GetBorderItem(_helper, "d:border/d:right");
                Border.Bottom = GetBorderItem(_helper, "d:border/d:bottom");
                Border.Top = GetBorderItem(_helper, "d:border/d:top");

                Fill.PatternType = GetPatternTypeEnum(_helper.GetXmlNodeString("d:fill/d:patternFill/@patternType"));
                Fill.BackgroundColor = GetColor(_helper, "d:fill/d:patternFill/d:bgColor/");
                Fill.PatternColor = GetColor(_helper, "d:fill/d:patternFill/d:fgColor/");
            }
            else
            {
                _helper = new XmlHelperInstance(nameSpaceManager);
            }
            _helper.SchemaNodeOrder = new string[] { "font", "numFmt", "fill", "border" };
        }
        private ExcelDxfBorderItem GetBorderItem(XmlHelperInstance helper, string path)
        {
            ExcelDxfBorderItem bi = new ExcelDxfBorderItem(_styles);
            bi.Style = GetBorderStyleEnum(helper.GetXmlNodeString(path+"/@style"));
            bi.Color = GetColor(helper, path+"/d:color");
            return bi;
        }
        private ExcelBorderStyle GetBorderStyleEnum(string style)
        {
            if (style == "") return ExcelBorderStyle.None;
            string sInStyle = style.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + style.Substring(1, style.Length - 1);
            try
            {
                return (ExcelBorderStyle)Enum.Parse(typeof(ExcelBorderStyle), sInStyle);
            }
            catch
            {
                return ExcelBorderStyle.None;
            }

        }
        private ExcelFillStyle GetPatternTypeEnum(string patternType)
        {
            if (patternType == "") return ExcelFillStyle.None;
            patternType = patternType.Substring(0, 1).ToUpper(CultureInfo.InvariantCulture) + patternType.Substring(1, patternType.Length - 1);
            try
            {
                return (ExcelFillStyle)Enum.Parse(typeof(ExcelFillStyle), patternType);
            }
            catch
            {
                return ExcelFillStyle.None;
            }
        }
        private ExcelDxfColor GetColor(XmlHelperInstance helper, string path)
        {            
            ExcelDxfColor ret = new ExcelDxfColor(_styles);
            ret.Theme = helper.GetXmlNodeIntNull(path + "/@theme");
            ret.Index = helper.GetXmlNodeIntNull(path + "/@indexed");
            string rgb=helper.GetXmlNodeString(path + "/@rgb");
            if(rgb!="")
            {
                ret.Color = Color.FromArgb( int.Parse(rgb.Substring(0, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
                                            int.Parse(rgb.Substring(2, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
                                            int.Parse(rgb.Substring(4, 2), System.Globalization.NumberStyles.AllowHexSpecifier),
                                            int.Parse(rgb.Substring(6, 2), System.Globalization.NumberStyles.AllowHexSpecifier));
            }
            ret.Auto = helper.GetXmlNodeBoolNullable(path + "/@auto");
            ret.Tint = helper.GetXmlNodeDoubleNull(path + "/@tint");
            return ret;
        }
        private ExcelUnderLineType? GetUnderLineEnum(string value)
        {
            switch(value.ToLower(CultureInfo.InvariantCulture))
            {
                case "single":
                    return ExcelUnderLineType.Single;
                case "double":
                    return ExcelUnderLineType.Double;
                case "singleaccounting":
                    return ExcelUnderLineType.SingleAccounting;
                case "doubleaccounting":
                    return ExcelUnderLineType.DoubleAccounting;
                default:
                    return null;
            }
        }
        internal int DxfId { get; set; }
        public ExcelDxfFontBase Font { get; set; }
        public ExcelDxfNumberFormat NumberFormat { get; set; }
        public ExcelDxfFill Fill { get; set; }
        public ExcelDxfBorderBase Border { get; set; }
        protected internal override string Id
        {
            get
            {
                return NumberFormat.Id + Font.Id + Border.Id + Fill.Id +
                    (AllowChange ? "" : DxfId.ToString());//If allowchange is false we add the dxfID to ensure it's not used when conditional formatting is updated);
            }
        }
        protected internal override ExcelDxfStyleConditionalFormatting Clone()
        {
 	       var s=new ExcelDxfStyleConditionalFormatting(_helper.NameSpaceManager, null, _styles);
           s.Font = Font.Clone();
           s.NumberFormat = NumberFormat.Clone();
           s.Fill = Fill.Clone();
           s.Border = Border.Clone();
           return s;
        }

        protected internal override void CreateNodes(XmlHelper helper, string path)
        {
            if(Font.HasValue) Font.CreateNodes(helper, "d:font");
            if (NumberFormat.HasValue) NumberFormat.CreateNodes(helper, "d:numFmt");            
            if (Fill.HasValue) Fill.CreateNodes(helper, "d:fill");
            if (Border.HasValue) Border.CreateNodes(helper, "d:border");
        }
        protected internal override bool HasValue
        {
            get { return Font.HasValue || NumberFormat.HasValue || Fill.HasValue || Border.HasValue; }
        }
    }
}
