using System;
using System.Globalization;
using System.Xml;

namespace OfficeOpenXml.Style.Dxf;

public class ExcelDxfStyleConditionalFormatting : DxfStyleBase<ExcelDxfStyleConditionalFormatting> {
  private readonly XmlHelperInstance _helper;

  internal ExcelDxfStyleConditionalFormatting(
      XmlNamespaceManager nameSpaceManager,
      XmlNode topNode,
      ExcelStyles styles)
      : base(styles) {
    NumberFormat = new(_styles);
    Font = new(_styles);
    Border = new(_styles);
    Fill = new(_styles);
    if (topNode != null) {
      _helper = new(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(nameSpaceManager);
    }
    _helper.SchemaNodeOrder = new[] { "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) =>
    Enum.TryParse<ExcelBorderStyle>(style, true, out var result) ? result : ExcelBorderStyle.None;

  private ExcelFillStyle GetPatternTypeEnum(string patternType) =>
    Enum.TryParse<ExcelFillStyle>(patternType, true, out var result) ? result : 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");
    ret.Rgb = helper.GetXmlNodeString(path + "/@rgb");
    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 =>
    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 =>
    Font.HasValue || NumberFormat.HasValue || Fill.HasValue || Border.HasValue;
}
