/*******************************************************************************
 * 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;
using OfficeOpenXml.ConditionalFormatting;
using OfficeOpenXml.Style;
using OfficeOpenXml.Style.Dxf;
using OfficeOpenXml.Style.XmlAccess;

namespace OfficeOpenXml;

/// <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;
  }
}
