/*******************************************************************************
 * You may amend and distribute as you like, but don't remove this header!
 *
 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
 * See http://www.codeplex.com/EPPlus for details.
 *
 * Copyright (C) 2011  Jan K�llman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
 *
 * All code and executables are provided "as is" with no warranty either express or implied.
 * The author accepts no liability for any damage or loss of business that this product may cause.
 *
 * Code change notes:
 *
 * Author							Change						Date
 * ******************************************************************************
 * Jan K�llman		    Initial Release		        2009-10-01
 * Jan K�llman		    License changed GPL-->LGPL 2011-12-27
 *******************************************************************************/

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Xml;

namespace AppsheetEpplus;

/// <summary>
/// Containts all shared cell styles for a workbook
/// </summary>
public sealed class ExcelStyles : XmlHelper {
  private const string _numberFormatsPath = "d:styleSheet/d:numFmts";
  private const string _fontsPath = "d:styleSheet/d:fonts";
  private const string _fillsPath = "d:styleSheet/d:fills";
  private const string _bordersPath = "d:styleSheet/d:borders";
  private const string _cellStyleXfsPath = "d:styleSheet/d:cellStyleXfs";
  private const string _cellXfsPath = "d:styleSheet/d:cellXfs";
  private const string _cellStylesPath = "d:styleSheet/d:cellStyles";
  private const string _dxfsPath = "d:styleSheet/d:dxfs";

  //internal Dictionary<int, ExcelXfs> Styles = new Dictionary<int, ExcelXfs>();
  private readonly XmlDocument _styleXml;
  private readonly ExcelWorkbook _wb;
  private readonly XmlNamespaceManager _nameSpaceManager;
  internal int _nextDfxNumFmtID = 164;

  protected override ImmutableArray<string> SchemaNodeOrder { get; } = [
    "numFmts",
    "fonts",
    "fills",
    "borders",
    "cellStyleXfs",
    "cellXfs",
    "cellStyles",
    "dxfs",
  ];

  internal ExcelStyles(XmlNamespaceManager nameSpaceManager, XmlDocument xml, ExcelWorkbook wb)
      : base(nameSpaceManager, xml) {
    _styleXml = xml;
    _wb = wb;
    _nameSpaceManager = nameSpaceManager;
    LoadFromDocument();
  }

  /// <summary>
  /// Loads the style XML to memory
  /// </summary>
  private void LoadFromDocument() {
    //NumberFormats
    ExcelNumberFormatXml.AddBuildIn(NameSpaceManager, NumberFormats);
    XmlNode numNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
    if (numNode != null) {
      foreach (XmlNode n in numNode) {
        ExcelNumberFormatXml nf = new ExcelNumberFormatXml(_nameSpaceManager, n);
        NumberFormats.Add(nf.Id, nf);
        if (nf.NumFmtId >= NumberFormats.NextId) {
          NumberFormats.NextId = nf.NumFmtId + 1;
        }
      }
    }

    //Fonts
    XmlNode fontNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
    foreach (XmlNode n in fontNode) {
      ExcelFontXml f = new ExcelFontXml(_nameSpaceManager, n);
      Fonts.Add(f.Id, f);
    }

    //Fills
    XmlNode fillNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
    foreach (XmlNode n in fillNode) {
      ExcelFillXml f;
      if (n.FirstChild != null && n.FirstChild.LocalName == "gradientFill") {
        f = new ExcelGradientFillXml(_nameSpaceManager, n);
      } else {
        f = new(_nameSpaceManager, n);
      }
      Fills.Add(f.Id, f);
    }

    //Borders
    XmlNode borderNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
    foreach (XmlNode n in borderNode) {
      ExcelBorderXml b = new ExcelBorderXml(_nameSpaceManager, n);
      Borders.Add(b.Id, b);
    }

    //cellStyleXfs
    XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
    if (styleXfsNode != null) {
      foreach (XmlNode n in styleXfsNode) {
        ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
        CellStyleXfs.Add(item.Id, item);
      }
    }

    XmlNode styleNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
    for (int i = 0; i < styleNode.ChildNodes.Count; i++) {
      XmlNode n = styleNode.ChildNodes[i];
      ExcelXfs item = new ExcelXfs(_nameSpaceManager, n, this);
      CellXfs.Add(item.Id, item);
    }

    //cellStyle
    XmlNode namedStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
    if (namedStyleNode != null) {
      foreach (XmlNode n in namedStyleNode) {
        ExcelNamedStyleXml item = new ExcelNamedStyleXml(_nameSpaceManager, n, this);
        NamedStyles.Add(item.Name, item);
      }
    }

    //dxfsPath
    XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
    if (dxfsNode != null) {
      foreach (XmlNode x in dxfsNode) {
        ExcelDxfStyleConditionalFormatting item = new ExcelDxfStyleConditionalFormatting(
            _nameSpaceManager,
            x,
            this);
        Dxfs.Add(item.Id, item);
      }
    }
  }

  internal ExcelStyle GetStyleObject(int id, int positionId, string address) {
    if (id < 0) {
      id = 0;
    }
    return new(this, PropertyChange, positionId, address, id);
  }

  /// <summary>
  /// Handels changes of properties on the style objects
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  /// <returns></returns>
  internal int PropertyChange(StyleBase sender, StyleChangeEventArgs e) {
    var address = new ExcelAddressBase(e.Address);
    var ws = _wb.Worksheets[e.PositionID];
    Dictionary<int, int> styleCashe = new Dictionary<int, int>();
    //Set single address
    SetStyleAddress(sender, e, address, ws, ref styleCashe);
    if (address.Addresses != null) {
      //Handle multiaddresses
      foreach (var innerAddress in address.Addresses) {
        SetStyleAddress(sender, e, innerAddress, ws, ref styleCashe);
      }
    }
    return 0;
  }

  private void SetStyleAddress(
      StyleBase sender,
      StyleChangeEventArgs e,
      ExcelAddressBase address,
      ExcelWorksheet ws,
      ref Dictionary<int, int> styleCashe) {
    if (address.Start.Column == 0 || address.Start.Row == 0) {
      throw (new("error address"));
    }
    //Columns
    if (address.Start.Row == 1 && address.End.Row == ExcelPackage.MaxRows) {
      ExcelColumn column;
      int col = address.Start.Column,
          row = 0;
      //Get the startcolumn
      if (!ws._values.Exists(0, address.Start.Column)) {
        column = ws.Column(address.Start.Column);
      } else {
        column = (ExcelColumn)ws._values.GetValue(0, address.Start.Column);
      }

      while (column.ColumnMin <= address.End.Column) {
        if (column.ColumnMax > address.End.Column) {
          var newCol = ws.CopyColumn(column, address.End.Column + 1, column.ColumnMax);
          column.ColumnMax = address.End.Column;
        }
        var s = ws._styles.GetValue(0, column.ColumnMin);
        if (styleCashe.ContainsKey(s)) {
          ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
        } else {
          ExcelXfs st = CellXfs[s];
          int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
          styleCashe.Add(s, newId);
          ws.SetStyle(0, column.ColumnMin, newId);
        }

        //index++;

        if (!ws._values.NextCell(ref row, ref col) || row > 0) {
          column._columnMax = address.End.Column;
          break;
        }
        column = (ws._values.GetValue(0, col) as ExcelColumn);
      }

      if (column._columnMax < address.End.Column) {
        var newCol = ws.Column(column._columnMax + 1);
        newCol._columnMax = address.End.Column;

        var s = ws._styles.GetValue(0, column.ColumnMin);
        if (styleCashe.ContainsKey(s)) {
          ws.SetStyle(0, column.ColumnMin, styleCashe[s]);
        } else {
          ExcelXfs st = CellXfs[s];
          int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
          styleCashe.Add(s, newId);
          ws.SetStyle(0, column.ColumnMin, newId);
        }

        column._columnMax = address.End.Column;
      }

      //Set for individual cells in the span. We loop all cells here since the cells are sorted with columns first.
      var cse = new CellsStoreEnumerator<int>(
          ws._styles,
          1,
          address._fromCol,
          address._toRow,
          address._toCol);
      while (cse.Next()) {
        if (cse.Column >= address.Start.Column && cse.Column <= address.End.Column) {
          if (styleCashe.ContainsKey(cse.Value)) {
            ws.SetStyle(cse.Row, cse.Column, styleCashe[cse.Value]);
          } else {
            ExcelXfs st = CellXfs[cse.Value];
            int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
            styleCashe.Add(cse.Value, newId);
            cse.Value = newId;
            //ws.SetStyle(cse.Row, cse.Column, newId);
          }
        }
      }

      //Update cells with styled columns
      cse = new(ws._styles, 1, 0, address._toRow, 0);
      while (cse.Next()) {
        for (int c = address._fromRow; c <= address._toCol; c++) {
          if (!ws._styles.Exists(cse.Row, c)) {
            if (styleCashe.ContainsKey(cse.Value)) {
              ws.SetStyle(cse.Row, c, styleCashe[cse.Value]);
            } else {
              ExcelXfs st = CellXfs[cse.Value];
              int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
              styleCashe.Add(cse.Value, newId);
              ws.SetStyle(cse.Row, c, newId);
            }
          }
        }
      }
    }
    //Rows
    else if (address.Start.Column == 1 && address.End.Column == ExcelPackage.MaxColumns) {
      for (int rowNum = address.Start.Row; rowNum <= address.End.Row; rowNum++) {
        var s = ws._styles.GetValue(rowNum, 0);
        if (s == 0) {
          //iterate all columns and set the row to the style of the last column
          var cse = new CellsStoreEnumerator<int>(ws._styles, 0, 1, 0, ExcelPackage.MaxColumns);
          while (cse.Next()) {
            s = cse.Value;
            var c = ws._values.GetValue(cse.Row, cse.Column) as ExcelColumn;
            if (c != null && c.ColumnMax < ExcelPackage.MaxColumns) {
              for (int col = c.ColumnMin; col < c.ColumnMax; col++) {
                if (!ws._styles.Exists(rowNum, col)) {
                  ws._styles.SetValue(rowNum, col, s);
                }
              }
            }
          }
          ws.SetStyle(rowNum, 0, s);
        }
        if (styleCashe.ContainsKey(s)) {
          ws.SetStyle(rowNum, 0, styleCashe[s]);
        } else {
          ExcelXfs st = CellXfs[s];
          int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
          styleCashe.Add(s, newId);
          ws._styles.SetValue(rowNum, 0, newId);
          ws.SetStyle(rowNum, 0, newId);
        }
      }

      //Update individual cells
      var cse2 = new CellsStoreEnumerator<int>(
          ws._styles,
          address._fromRow,
          address._fromCol,
          address._toRow,
          address._toCol);
      while (cse2.Next()) {
        var s = cse2.Value;
        if (styleCashe.ContainsKey(s)) {
          ws.SetStyle(cse2.Row, cse2.Column, styleCashe[s]);
        } else {
          ExcelXfs st = CellXfs[s];
          int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
          styleCashe.Add(s, newId);
          cse2.Value = newId;
        }
      }

      //Update cells with styled rows
      cse2 = new(ws._styles, 0, 1, 0, address._toCol);
      while (cse2.Next()) {
        for (int r = address._fromRow; r <= address._toRow; r++) {
          if (!ws._styles.Exists(r, cse2.Column)) {
            var s = cse2.Value;
            if (styleCashe.ContainsKey(s)) {
              ws.SetStyle(r, cse2.Column, styleCashe[s]);
            } else {
              ExcelXfs st = CellXfs[s];
              int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
              styleCashe.Add(s, newId);
              ws.SetStyle(r, cse2.Column, newId);
            }
          }
        }
      }
    } else //Cellrange
    {
      for (int col = address.Start.Column; col <= address.End.Column; col++) {
        for (int row = address.Start.Row; row <= address.End.Row; row++) {
          var s = GetStyleId(ws, row, col);
          if (styleCashe.ContainsKey(s)) {
            ws.SetStyle(row, col, styleCashe[s]);
          } else {
            ExcelXfs st = CellXfs[s];
            int newId = st.GetNewId(CellXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
            styleCashe.Add(s, newId);
            ws.SetStyle(row, col, newId);
          }
        }
      }
    }
  }

  internal int GetStyleId(ExcelWorksheet ws, int row, int col) {
    int v = 0;
    if (ws._styles.Exists(row, col, ref v)) {
      return v;
    }
    if (ws._styles.Exists(
        row,
        0,
        ref v)) //First Row
    {
      return v;
    } // then column
    if (ws._styles.Exists(0, col, ref v)) {
      return v;
    }
    int r = 0,
        c = col;
    if (ws._values.PrevCell(ref r, ref c)) {
      var column = ws._values.GetValue(0, c) as ExcelColumn;
      if (column != null
          && column.ColumnMax
              >= col) //Fixes issue 15174
      {
        return ws._styles.GetValue(0, c);
      }
      return 0;
    }
    return 0;
  }

  /// <summary>
  /// Handles property changes on Named styles.
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  /// <returns></returns>
  internal int NamedStylePropertyChange(StyleBase sender, StyleChangeEventArgs e) {
    int index = NamedStyles.FindIndexById(e.Address);
    if (index >= 0) {
      int newId = CellStyleXfs[NamedStyles[index].StyleXfId]
          .GetNewId(CellStyleXfs, sender, e.StyleClass, e.StyleProperty, e.Value);
      int prevIx = NamedStyles[index].StyleXfId;
      NamedStyles[index].StyleXfId = newId;
      NamedStyles[index].Style.Index = newId;

      NamedStyles[index].XfId = int.MinValue;
      foreach (var style in CellXfs) {
        if (style.XfId == prevIx) {
          style.XfId = newId;
        }
      }
    }
    return 0;
  }

  public ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats = new();
  public ExcelStyleCollection<ExcelFontXml> Fonts = new();
  public ExcelStyleCollection<ExcelFillXml> Fills = new();
  public ExcelStyleCollection<ExcelBorderXml> Borders = new();
  public ExcelStyleCollection<ExcelXfs> CellStyleXfs = new();
  public ExcelStyleCollection<ExcelXfs> CellXfs = new();
  public ExcelStyleCollection<ExcelNamedStyleXml> NamedStyles = new();
  public ExcelStyleCollection<ExcelDxfStyleConditionalFormatting> Dxfs = new();

  internal string Id => "";

  public ExcelNamedStyleXml CreateNamedStyle(string name) {
    return CreateNamedStyle(name, null);
  }

  public ExcelNamedStyleXml CreateNamedStyle(string name, ExcelStyle template) {
    if (_wb.Styles.NamedStyles.ExistsKey(name)) {
      throw new(string.Format("Key {0} already exists in collection", name));
    }

    ExcelNamedStyleXml style;
    style = new(NameSpaceManager, this);
    int xfIdCopy,
        positionId;
    ExcelStyles styles;
    if (template == null) {
      //                style.Style = new ExcelStyle(this, NamedStylePropertyChange, -1, name, 0);
      xfIdCopy = 0;
      positionId = -1;
      styles = this;
    } else {
      if (template.PositionID < 0 && template.Styles == this) {
        xfIdCopy = template.Index;
        positionId = template.PositionID;
        styles = this;
        //style.Style = new ExcelStyle(this, NamedStylePropertyChange, Template.PositionID, name, Template.Index);
        //style.StyleXfId = Template.Index;
      } else {
        xfIdCopy = template.XfId;
        positionId = -1;
        styles = template.Styles;
      }
    }
    //Clone namedstyle
    int styleXfId = CloneStyle(styles, xfIdCopy, true);
    //Close cells style
    CellStyleXfs[styleXfId].XfId = CellStyleXfs.Count - 1;
    int xfid = CloneStyle(styles, xfIdCopy, false, true); //Always add a new style (We create a new named style here)
    CellXfs[xfid].XfId = styleXfId;
    style.Style = new(this, NamedStylePropertyChange, positionId, name, styleXfId);
    style.StyleXfId = styleXfId;

    style.Name = name;
    int ix = _wb.Styles.NamedStyles.Add(style.Name, style);
    style.Style.SetIndex(ix);
    //style.Style.XfId = ix;
    return style;
  }

  public void UpdateXml() {
    RemoveUnusedStyles();

    //NumberFormat
    XmlNode nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
    if (nfNode == null) {
      CreateNode(_numberFormatsPath, true);
      nfNode = _styleXml.SelectSingleNode(_numberFormatsPath, _nameSpaceManager);
    } else {
      nfNode.RemoveAll();
    }

    int count = 0;
    int normalIx = NamedStyles.FindIndexById("Normal");
    if (NamedStyles.Count > 0
        && normalIx >= 0
        && NamedStyles[normalIx].Style.Numberformat.NumFmtID >= 164) {
      ExcelNumberFormatXml nf = NumberFormats[NumberFormats.FindIndexById(
            NamedStyles[normalIx].Style.Numberformat.Id)];
      nfNode.AppendChild(
          nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
      nf.newID = count++;
    }
    foreach (ExcelNumberFormatXml nf in NumberFormats) {
      if (!nf.BuildIn /*&& nf.newID<0*/) //Buildin formats are not updated.
      {
        nfNode.AppendChild(
            nf.CreateXmlNode(_styleXml.CreateElement("numFmt", ExcelPackage._schemaMain)));
        nf.newID = count;
        count++;
      }
    }
    (nfNode as XmlElement).SetAttribute("count", count.ToString());

    //Font
    count = 0;
    XmlNode fntNode = _styleXml.SelectSingleNode(_fontsPath, _nameSpaceManager);
    fntNode.RemoveAll();

    //Normal should be first in the collection
    if (NamedStyles.Count > 0 && normalIx >= 0 && NamedStyles[normalIx].Style.Font.Index > 0) {
      ExcelFontXml fnt = Fonts[NamedStyles[normalIx].Style.Font.Index];
      fntNode.AppendChild(
          fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
      fnt.newID = count++;
    }

    foreach (ExcelFontXml fnt in Fonts) {
      if (fnt.useCnt
          > 0 /* && fnt.newID<0*/) {
        fntNode.AppendChild(
            fnt.CreateXmlNode(_styleXml.CreateElement("font", ExcelPackage._schemaMain)));
        fnt.newID = count;
        count++;
      }
    }
    (fntNode as XmlElement).SetAttribute("count", count.ToString());

    //Fills
    count = 0;
    XmlNode fillsNode = _styleXml.SelectSingleNode(_fillsPath, _nameSpaceManager);
    fillsNode.RemoveAll();
    Fills[0].useCnt = 1; //Must exist (none);
    Fills[1].useCnt = 1; //Must exist (gray125);
    foreach (ExcelFillXml fill in Fills) {
      if (fill.useCnt > 0) {
        fillsNode.AppendChild(
            fill.CreateXmlNode(_styleXml.CreateElement("fill", ExcelPackage._schemaMain)));
        fill.newID = count;
        count++;
      }
    }

    (fillsNode as XmlElement).SetAttribute("count", count.ToString());

    //Borders
    count = 0;
    XmlNode bordersNode = _styleXml.SelectSingleNode(_bordersPath, _nameSpaceManager);
    bordersNode.RemoveAll();
    Borders[0].useCnt = 1; //Must exist blank;
    foreach (ExcelBorderXml border in Borders) {
      if (border.useCnt > 0) {
        bordersNode.AppendChild(
            border.CreateXmlNode(_styleXml.CreateElement("border", ExcelPackage._schemaMain)));
        border.newID = count;
        count++;
      }
    }
    (bordersNode as XmlElement).SetAttribute("count", count.ToString());

    XmlNode styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
    if (styleXfsNode == null && NamedStyles.Count > 0) {
      CreateNode(_cellStyleXfsPath);
      styleXfsNode = _styleXml.SelectSingleNode(_cellStyleXfsPath, _nameSpaceManager);
    }
    if (NamedStyles.Count > 0) {
      styleXfsNode.RemoveAll();
    }
    //NamedStyles
    count = normalIx > -1 ? 1 : 0; //If we have a normal style, we make sure it's added first.

    XmlNode cellStyleNode = _styleXml.SelectSingleNode(_cellStylesPath, _nameSpaceManager);
    if (cellStyleNode != null) {
      cellStyleNode.RemoveAll();
    }
    XmlNode cellXfsNode = _styleXml.SelectSingleNode(_cellXfsPath, _nameSpaceManager);
    cellXfsNode.RemoveAll();

    if (NamedStyles.Count > 0 && normalIx >= 0) {
      NamedStyles[normalIx].newID = 0;
      AddNamedStyle(0, styleXfsNode, cellXfsNode, NamedStyles[normalIx]);
    }
    foreach (ExcelNamedStyleXml style in NamedStyles) {
      if (!style.Name.Equals("normal", StringComparison.InvariantCultureIgnoreCase)) {
        AddNamedStyle(count++, styleXfsNode, cellXfsNode, style);
      } else {
        style.newID = 0;
      }
      cellStyleNode.AppendChild(
          style.CreateXmlNode(_styleXml.CreateElement("cellStyle", ExcelPackage._schemaMain)));
    }
    if (cellStyleNode != null) {
      (cellStyleNode as XmlElement).SetAttribute("count", count.ToString());
    }
    if (styleXfsNode != null) {
      (styleXfsNode as XmlElement).SetAttribute("count", count.ToString());
    }

    //CellStyle
    int xfix = 0;
    foreach (ExcelXfs xf in CellXfs) {
      if (xf.useCnt > 0 && !(normalIx >= 0 && NamedStyles[normalIx].XfId == xfix)) {
        cellXfsNode.AppendChild(
            xf.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
        xf.newID = count;
        count++;
      }
      xfix++;
    }
    (cellXfsNode as XmlElement).SetAttribute("count", count.ToString());

    //Set dxf styling for conditional Formatting
    XmlNode dxfsNode = _styleXml.SelectSingleNode(_dxfsPath, _nameSpaceManager);
    foreach (var ws in _wb.Worksheets) {
      if (ws is ExcelChartsheet) {
        continue;
      }
      foreach (var cf in ws.ConditionalFormatting) {
        if (cf.Style.HasValue) {
          int ix = Dxfs.FindIndexById(cf.Style.Id);
          if (ix < 0) {
            ((ExcelConditionalFormattingRule)cf).DxfId = Dxfs.Count;
            Dxfs.Add(cf.Style.Id, cf.Style);
            var elem = ((XmlDocument)TopNode).CreateElement("d", "dxf", ExcelPackage._schemaMain);
            cf.Style.CreateNodes(new XmlHelperInstance(NameSpaceManager, elem), "");
            dxfsNode.AppendChild(elem);
          } else {
            ((ExcelConditionalFormattingRule)cf).DxfId = ix;
          }
        }
      }
    }
    if (dxfsNode != null) {
      (dxfsNode as XmlElement).SetAttribute("count", Dxfs.Count.ToString());
    }
  }

  private void AddNamedStyle(
      int id,
      XmlNode styleXfsNode,
      XmlNode cellXfsNode,
      ExcelNamedStyleXml style) {
    var styleXfs = CellStyleXfs[style.StyleXfId];
    styleXfsNode.AppendChild(
        styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain), true));
    styleXfs.newID = id;
    styleXfs.XfId = style.StyleXfId;

    var ix = CellXfs.FindIndexById(styleXfs.Id);
    if (ix < 0) {
      cellXfsNode.AppendChild(
          styleXfs.CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
    } else {
      if (id < 0) {
        CellXfs[ix].XfId = id;
      }
      cellXfsNode.AppendChild(
          CellXfs[ix].CreateXmlNode(_styleXml.CreateElement("xf", ExcelPackage._schemaMain)));
      CellXfs[ix].useCnt = 0;
      CellXfs[ix].newID = id;
    }

    if (style.XfId >= 0) {
      style.XfId = CellXfs[style.XfId].newID;
    } else {
      style.XfId = 0;
    }
  }

  private void RemoveUnusedStyles() {
    CellXfs[0].useCnt = 1; //First item is allways used.
    foreach (ExcelWorksheet sheet in _wb.Worksheets) {
      var cse = new CellsStoreEnumerator<int>(sheet._styles);
      while (cse.Next()) {
        var v = cse.Value;
        if (v >= 0) {
          CellXfs[v].useCnt++;
        }
      }
    }
    foreach (ExcelNamedStyleXml ns in NamedStyles) {
      CellStyleXfs[ns.StyleXfId].useCnt++;
    }

    foreach (ExcelXfs xf in CellXfs) {
      if (xf.useCnt > 0) {
        if (xf.FontId >= 0) {
          Fonts[xf.FontId].useCnt++;
        }
        if (xf.FillId >= 0) {
          Fills[xf.FillId].useCnt++;
        }
        if (xf.BorderId >= 0) {
          Borders[xf.BorderId].useCnt++;
        }
      }
    }
    foreach (ExcelXfs xf in CellStyleXfs) {
      if (xf.useCnt > 0) {
        if (xf.FontId >= 0) {
          Fonts[xf.FontId].useCnt++;
        }
        if (xf.FillId >= 0) {
          Fills[xf.FillId].useCnt++;
        }
        if (xf.BorderId >= 0) {
          Borders[xf.BorderId].useCnt++;
        }
      }
    }
  }

  internal int GetStyleIdFromName(string name) {
    int i = NamedStyles.FindIndexById(name);
    if (i >= 0) {
      int id = NamedStyles[i].XfId;
      if (id < 0) {
        int styleXfId = NamedStyles[i].StyleXfId;
        ExcelXfs newStyle = CellStyleXfs[styleXfId].Copy();
        newStyle.XfId = styleXfId;
        id = CellXfs.FindIndexById(newStyle.Id);
        if (id < 0) {
          id = CellXfs.Add(newStyle.Id, newStyle);
        }
        NamedStyles[i].XfId = id;
      }
      return id;
    }
    return 0;
    //throw(new Exception("Named style does not exist"));
  }

  private string GetXmlNode(XmlNode node) {
    if (node == null) {
      return "";
    }
    if (node.Value != null) {
      return node.Value;
    }
    return "";
  }

  internal int CloneStyle(ExcelStyles style, int styleId) {
    return CloneStyle(style, styleId, false, false);
  }

  internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle) {
    return CloneStyle(style, styleId, isNamedStyle, false);
  }

  internal int CloneStyle(ExcelStyles style, int styleId, bool isNamedStyle, bool allwaysAdd) {
    var xfs = isNamedStyle ? style.CellStyleXfs[styleId] : style.CellXfs[styleId];
    ExcelXfs newXfs = xfs.Copy(this);
    //Numberformat
    if (xfs.NumberFormatId > 0) {
      //rake36: Two problems here...
      //rake36:  1. the first time through when format stays equal to String.Empty, it adds a string.empty to the list of Number Formats
      //rake36:  2. when adding a second sheet, if the numberformatid == 164, it finds the 164 added by previous sheets but was using the array index
      //rake36:      for the numberformatid

      string format = string.Empty;
      foreach (var fmt in style.NumberFormats) {
        if (fmt.NumFmtId == xfs.NumberFormatId) {
          format = fmt.Format;
          break;
        }
      }
      //rake36: Don't add another format if it's blank
      if (!String.IsNullOrEmpty(format)) {
        int ix = NumberFormats.FindIndexById(format);
        if (ix < 0) {
          var item = new ExcelNumberFormatXml(NameSpaceManager) {
            Format = format,
            NumFmtId = NumberFormats.NextId++,
          };
          NumberFormats.Add(format, item);
          //rake36: Use the just added format id
          newXfs.NumberFormatId = item.NumFmtId;
        } else {
          //rake36: Use the format id defined by the index... not the index itself
          newXfs.NumberFormatId = NumberFormats[ix].NumFmtId;
        }
      }
    }

    //Font
    if (xfs.FontId > -1) {
      int ix = Fonts.FindIndexById(xfs.Font.Id);
      if (ix < 0) {
        ExcelFontXml item = style.Fonts[xfs.FontId].Copy();
        ix = Fonts.Add(xfs.Font.Id, item);
      }
      newXfs.FontId = ix;
    }

    //Border
    if (xfs.BorderId > -1) {
      int ix = Borders.FindIndexById(xfs.Border.Id);
      if (ix < 0) {
        ExcelBorderXml item = style.Borders[xfs.BorderId].Copy();
        ix = Borders.Add(xfs.Border.Id, item);
      }
      newXfs.BorderId = ix;
    }

    //Fill
    if (xfs.FillId > -1) {
      int ix = Fills.FindIndexById(xfs.Fill.Id);
      if (ix < 0) {
        var item = style.Fills[xfs.FillId].Copy();
        ix = Fills.Add(xfs.Fill.Id, item);
      }
      newXfs.FillId = ix;
    }

    //Named style reference
    if (xfs.XfId > 0) {
      var id = style.CellStyleXfs[xfs.XfId].Id;
      var newId = CellStyleXfs.FindIndexById(id);
      if (newId >= 0) {
        newXfs.XfId = newId;
      } else if (style._wb != _wb
          && allwaysAdd
              == false) //Not the same workbook, copy the namedstyle to the workbook or match the id
      {
        var nsFind = style.NamedStyles.ToDictionary(d => (d.StyleXfId));
        if (nsFind.ContainsKey(xfs.XfId)) {
          var st = nsFind[xfs.XfId];
          if (NamedStyles.ExistsKey(st.Name)) {
            newXfs.XfId = NamedStyles.FindIndexById(st.Name);
          } else {
            var ns = CreateNamedStyle(st.Name, st.Style);
            newXfs.XfId = NamedStyles.Count - 1;
          }
        }
      }
    }

    int index;
    if (isNamedStyle) {
      index = CellStyleXfs.Add(newXfs.Id, newXfs);
    } else {
      if (allwaysAdd) {
        index = CellXfs.Add(newXfs.Id, newXfs);
      } else {
        index = CellXfs.FindIndexById(newXfs.Id);
        if (index < 0) {
          index = CellXfs.Add(newXfs.Id, newXfs);
        }
      }
    }
    return index;
  }
}
