/*******************************************************************************
 * 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		Added		21-MAR-2011
 * Jan Källman		License changed GPL-->LGPL 2011-12-16
 *******************************************************************************/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;

namespace OfficeOpenXml.Table.PivotTable;

/// <summary>
/// Defines the axis for a PivotTable
/// </summary>
public enum ePivotFieldAxis {
  /// <summary>
  /// None
  /// </summary>
  None = -1,

  /// <summary>
  /// Column axis
  /// </summary>
  Column,

  /// <summary>
  /// Page axis (Include Count Filter)
  ///
  /// </summary>
  Page,

  /// <summary>
  /// Row axis
  /// </summary>
  Row,

  /// <summary>
  /// Values axis
  /// </summary>
  Values,
}

/// <summary>
/// Build-in table row functions
/// </summary>
public enum DataFieldFunctions {
  Average,
  Count,
  CountNums,
  Max,
  Min,
  Product,
  None,
  StdDev,
  StdDevP,
  Sum,
  Var,
  VarP,
}

/// <summary>
/// Defines the data formats for a field in the PivotTable
/// </summary>
public enum eShowDataAs {
  /// <summary>
  /// Indicates the field is shown as the "difference from" a value.
  /// </summary>
  Difference,

  /// <summary>
  /// Indicates the field is shown as the "index.
  /// </summary>
  Index,

  /// <summary>
  /// Indicates that the field is shown as its normal datatype.
  /// </summary>
  Normal,

  /// <summary>
  /// /Indicates the field is show as the "percentage of" a value
  /// </summary>
  Percent,

  /// <summary>
  /// Indicates the field is shown as the "percentage difference from" a value.
  /// </summary>
  PercentDiff,

  /// <summary>
  /// Indicates the field is shown as the percentage of column.
  /// </summary>
  PercentOfCol,

  /// <summary>
  /// Indicates the field is shown as the percentage of row
  /// </summary>
  PercentOfRow,

  /// <summary>
  /// Indicates the field is shown as percentage of total.
  /// </summary>
  PercentOfTotal,

  /// <summary>
  /// Indicates the field is shown as running total in the table.
  /// </summary>
  RunTotal,
}

/// <summary>
/// Built-in subtotal functions
/// </summary>
[Flags]
public enum eSubTotalFunctions {
  None = 1,
  Count = 2,
  CountA = 4,
  Avg = 8,
  Default = 16,
  Min = 32,
  Max = 64,
  Product = 128,
  StdDev = 256,
  StdDevP = 512,
  Sum = 1024,
  Var = 2048,
  VarP = 4096,
}

/// <summary>
/// Data grouping
/// </summary>
[Flags]
public enum eDateGroupBy {
  Years = 1,
  Quarters = 2,
  Months = 4,
  Days = 8,
  Hours = 16,
  Minutes = 32,
  Seconds = 64,
}

/// <summary>
/// Sorting
/// </summary>
public enum eSortType {
  None,
  Ascending,
  Descending,
}

/// <summary>
/// A pivot table field.
/// </summary>
public class ExcelPivotTableField : XmlHelper {
  internal ExcelPivotTable _table;

  internal ExcelPivotTableField(
      XmlNamespaceManager ns,
      XmlNode topNode,
      ExcelPivotTable table,
      int index,
      int baseIndex)
      : base(ns, topNode) {
    Index = index;
    BaseIndex = baseIndex;
    _table = table;
  }

  public int Index { get; set; }

  internal int BaseIndex { get; set; }

  /// <summary>
  /// Name of the field
  /// </summary>
  public string Name {
    get {
      string v = GetXmlNodeString("@name");
      if (v == "") {
        return _cacheFieldHelper.GetXmlNodeString("@name");
      }
      return v;
    }
    set => SetXmlNodeString("@name", value);
  }

  /// <summary>
  /// Compact mode
  /// </summary>
  public bool Compact {
    get => GetXmlNodeBool("@compact");
    set => SetXmlNodeBool("@compact", value);
  }

  /// <summary>
  /// A boolean that indicates whether the items in this field should be shown in Outline form
  /// </summary>
  public bool Outline {
    get => GetXmlNodeBool("@outline");
    set => SetXmlNodeBool("@outline", value);
  }

  /// <summary>
  /// The custom text that is displayed for the subtotals label
  /// </summary>
  public bool SubtotalTop {
    get => GetXmlNodeBool("@subtotalTop");
    set => SetXmlNodeBool("@subtotalTop", value);
  }

  /// <summary>
  /// A boolean that indicates whether to show all items for this field
  /// </summary>
  public bool ShowAll {
    get => GetXmlNodeBool("@showAll");
    set => SetXmlNodeBool("@showAll", value);
  }

  /// <summary>
  /// The type of sort that is applied to this field
  /// </summary>
  public eSortType Sort {
    get {
      string v = GetXmlNodeString("@sortType");
      return v == "" ? eSortType.None : (eSortType)Enum.Parse(typeof(eSortType), v, true);
    }
    set {
      if (value == eSortType.None) {
        DeleteNode("@sortType");
      } else {
        SetXmlNodeString("@sortType", value.ToString().ToLower(CultureInfo.InvariantCulture));
      }
    }
  }

  /// <summary>
  /// A boolean that indicates whether manual filter is in inclusive mode
  /// </summary>
  public bool IncludeNewItemsInFilter {
    get => GetXmlNodeBool("@includeNewItemsInFilter");
    set => SetXmlNodeBool("@includeNewItemsInFilter", value);
  }

  /// <summary>
  /// Enumeration of the different subtotal operations that can be applied to page, row or column fields
  /// </summary>
  public eSubTotalFunctions SubTotalFunctions {
    get {
      eSubTotalFunctions ret = 0;
      XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
      if (nl.Count == 0) {
        return eSubTotalFunctions.None;
      }
      foreach (XmlAttribute item in nl) {
        try {
          ret |= (eSubTotalFunctions)Enum.Parse(typeof(eSubTotalFunctions), item.Value, true);
        } catch (ArgumentException ex) {
          throw new ArgumentException(
              "Unable to parse value of "
                  + item.Value
                  + " to a valid pivot table subtotal function",
              ex);
        }
      }
      return ret;
    }
    set {
      if ((value & eSubTotalFunctions.None) == eSubTotalFunctions.None
          && (value != eSubTotalFunctions.None)) {
        throw (new ArgumentException("Value None can not be combined with other values."));
      }
      if ((value & eSubTotalFunctions.Default) == eSubTotalFunctions.Default
          && (value != eSubTotalFunctions.Default)) {
        throw (new ArgumentException("Value Default can not be combined with other values."));
      }

      // remove old attribute
      XmlNodeList nl = TopNode.SelectNodes("d:items/d:item/@t", NameSpaceManager);
      if (nl.Count > 0) {
        foreach (XmlAttribute item in nl) {
          DeleteNode("@" + item.Value + "Subtotal");
          item.OwnerElement.ParentNode.RemoveChild(item.OwnerElement);
        }
      }

      if (value == eSubTotalFunctions.None) {
        // for no subtotals, set defaultSubtotal to off
        SetXmlNodeBool("@defaultSubtotal", false);
        TopNode.InnerXml = "";
      } else {
        string innerXml = "";
        int count = 0;
        foreach (eSubTotalFunctions e in Enum.GetValues(typeof(eSubTotalFunctions))) {
          if ((value & e) == e) {
            var newTotalType = e.ToString();
            var totalType =
                char.ToLower(newTotalType[0], CultureInfo.InvariantCulture)
                    + newTotalType.Substring(1);
            // add new attribute
            SetXmlNodeBool("@" + totalType + "Subtotal", true);
            innerXml += "<item t=\"" + totalType + "\" />";
            count++;
          }
        }
        TopNode.InnerXml = string.Format("<items count=\"{0}\">{1}</items>", count, innerXml);
      }
    }
  }

  /// <summary>
  /// Type of axis
  /// </summary>
  public ePivotFieldAxis Axis {
    get {
      switch (GetXmlNodeString("@axis")) {
        case "axisRow":
          return ePivotFieldAxis.Row;
        case "axisCol":
          return ePivotFieldAxis.Column;
        case "axisPage":
          return ePivotFieldAxis.Page;
        case "axisValues":
          return ePivotFieldAxis.Values;
        default:
          return ePivotFieldAxis.None;
      }
    }
    internal set {
      switch (value) {
        case ePivotFieldAxis.Row:
          SetXmlNodeString("@axis", "axisRow");
          break;
        case ePivotFieldAxis.Column:
          SetXmlNodeString("@axis", "axisCol");
          break;
        case ePivotFieldAxis.Values:
          SetXmlNodeString("@axis", "axisValues");
          break;
        case ePivotFieldAxis.Page:
          SetXmlNodeString("@axis", "axisPage");
          break;
        default:
          DeleteNode("@axis");
          break;
      }
    }
  }

  /// <summary>
  /// If the field is a row field
  /// </summary>
  public bool IsRowField {
    get =>
      (TopNode.SelectSingleNode(
              string.Format("../../d:rowFields/d:field[@x={0}]", Index),
              NameSpaceManager) != null);
    internal set {
      if (value) {
        var rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
        if (rowsNode == null) {
          _table.CreateNode("d:rowFields");
        }
        rowsNode = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);

        AppendField(rowsNode, Index, "field", "x");
        if (BaseIndex == Index) {
          TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
        } else {
          TopNode.InnerXml = "<items count=\"0\"></items>";
        }
      } else {
        XmlElement node =
            TopNode.SelectSingleNode(
                string.Format("../../d:rowFields/d:field[@x={0}]", Index),
                NameSpaceManager) as XmlElement;
        if (node != null) {
          node.ParentNode.RemoveChild(node);
        }
      }
    }
  }

  /// <summary>
  /// If the field is a column field
  /// </summary>
  public bool IsColumnField {
    get =>
      (TopNode.SelectSingleNode(
              string.Format("../../d:colFields/d:field[@x={0}]", Index),
              NameSpaceManager) != null);
    internal set {
      if (value) {
        var columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
        if (columnsNode == null) {
          _table.CreateNode("d:colFields");
        }
        columnsNode = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);

        AppendField(columnsNode, Index, "field", "x");
        if (BaseIndex == Index) {
          TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";
        } else {
          TopNode.InnerXml = "<items count=\"0\"></items>";
        }
      } else {
        XmlElement node =
            TopNode.SelectSingleNode(
                string.Format("../../d:colFields/d:field[@x={0}]", Index),
                NameSpaceManager) as XmlElement;
        if (node != null) {
          node.ParentNode.RemoveChild(node);
        }
      }
    }
  }

  /// <summary>
  /// If the field is a datafield
  /// </summary>
  public bool IsDataField => GetXmlNodeBool("@dataField", false);

  /// <summary>
  /// If the field is a page field.
  /// </summary>
  public bool IsPageField {
    get => (Axis == ePivotFieldAxis.Page);
    internal set {
      if (value) {
        var dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
        if (dataFieldsNode == null) {
          _table.CreateNode("d:pageFields");
          dataFieldsNode = TopNode.SelectSingleNode("../../d:pageFields", NameSpaceManager);
        }

        TopNode.InnerXml = "<items count=\"1\"><item t=\"default\" /></items>";

        XmlElement node = AppendField(dataFieldsNode, Index, "pageField", "fld");
        _pageFieldSettings = new(NameSpaceManager, node, this, Index);
      } else {
        _pageFieldSettings = null;
        XmlElement node =
            TopNode.SelectSingleNode(
                string.Format("../../d:pageFields/d:pageField[@fld={0}]", Index),
                NameSpaceManager) as XmlElement;
        if (node != null) {
          node.ParentNode.RemoveChild(node);
        }
      }
    }
  }

  //public ExcelPivotGrouping DateGrouping
  //{

  //}
  internal ExcelPivotTablePageFieldSettings _pageFieldSettings;

  public ExcelPivotTablePageFieldSettings PageFieldSettings => _pageFieldSettings;

  internal eDateGroupBy DateGrouping { get; set; }

  private ExcelPivotTableFieldGroup _grouping;

  /// <summary>
  /// Grouping settings.
  /// Null if the field has no grouping otherwise ExcelPivotTableFieldNumericGroup or ExcelPivotTableFieldNumericGroup.
  /// </summary>
  public ExcelPivotTableFieldGroup Grouping => _grouping;

  internal XmlElement AppendField(
      XmlNode rowsNode,
      int index,
      string fieldNodeText,
      string indexAttrText) {
    XmlElement prevField = null,
        newElement;
    foreach (XmlElement field in rowsNode.ChildNodes) {
      string x = field.GetAttribute(indexAttrText);
      int fieldIndex;
      if (int.TryParse(x, out fieldIndex)) {
        if (fieldIndex
            == index) //Row already exists
        {
          return field;
        }
        //else if (fieldIndex > index)
        //{
        //    newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage.schemaMain);
        //    newElement.SetAttribute(indexAttrText, index.ToString());
        //    rowsNode.InsertAfter(newElement, field);
        //}
      }
      prevField = field;
    }
    newElement = rowsNode.OwnerDocument.CreateElement(fieldNodeText, ExcelPackage._schemaMain);
    newElement.SetAttribute(indexAttrText, index.ToString());
    rowsNode.InsertAfter(newElement, prevField);

    return newElement;
  }

  internal XmlHelperInstance _cacheFieldHelper;

  internal void SetCacheFieldNode(XmlNode cacheField) {
    _cacheFieldHelper = new(NameSpaceManager, cacheField);
    var groupNode = cacheField.SelectSingleNode("d:fieldGroup", NameSpaceManager);
    if (groupNode != null) {
      var groupBy = groupNode.SelectSingleNode("d:rangePr/@groupBy", NameSpaceManager);
      if (groupBy == null) {
        _grouping = new ExcelPivotTableFieldNumericGroup(NameSpaceManager, cacheField);
      } else {
        DateGrouping = (eDateGroupBy)Enum.Parse(typeof(eDateGroupBy), groupBy.Value, true);
        _grouping = new ExcelPivotTableFieldDateGroup(NameSpaceManager, groupNode);
      }
    }
  }

  internal ExcelPivotTableFieldDateGroup SetDateGroup(
      eDateGroupBy groupBy,
      DateTime startDate,
      DateTime endDate,
      int interval) {
    ExcelPivotTableFieldDateGroup group;
    group = new(NameSpaceManager, _cacheFieldHelper.TopNode);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsDate", true);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNonDate", false);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);

    group.TopNode.InnerXml += string.Format(
        "<fieldGroup base=\"{0}\"><rangePr groupBy=\"{1}\" /><groupItems /></fieldGroup>",
        BaseIndex,
        groupBy.ToString().ToLower(CultureInfo.InvariantCulture));

    if (startDate.Year < 1900) {
      _cacheFieldHelper.SetXmlNodeString(
          "d:fieldGroup/d:rangePr/@startDate",
          "1900-01-01T00:00:00");
    } else {
      _cacheFieldHelper.SetXmlNodeString(
          "d:fieldGroup/d:rangePr/@startDate",
          startDate.ToString("s", CultureInfo.InvariantCulture));
      _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoStart", "0");
    }

    if (endDate == DateTime.MaxValue) {
      _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@endDate", "9999-12-31T00:00:00");
    } else {
      _cacheFieldHelper.SetXmlNodeString(
          "d:fieldGroup/d:rangePr/@endDate",
          endDate.ToString("s", CultureInfo.InvariantCulture));
      _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/d:rangePr/@autoEnd", "0");
    }

    int items = AddDateGroupItems(group, groupBy, startDate, endDate, interval);
    AddFieldItems(items);

    _grouping = group;
    return group;
  }

  internal ExcelPivotTableFieldNumericGroup SetNumericGroup(
      double start,
      double end,
      double interval) {
    ExcelPivotTableFieldNumericGroup group;
    group = new(NameSpaceManager, _cacheFieldHelper.TopNode);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsNumber", true);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsInteger", true);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsSemiMixedTypes", false);
    _cacheFieldHelper.SetXmlNodeBool("d:sharedItems/@containsString", false);

    group.TopNode.InnerXml += string.Format(
        "<fieldGroup base=\"{0}\"><rangePr autoStart=\"0\" autoEnd=\"0\" startNum=\"{1}\" endNum=\"{2}\" groupInterval=\"{3}\"/><groupItems /></fieldGroup>",
        BaseIndex,
        start.ToString(CultureInfo.InvariantCulture),
        end.ToString(CultureInfo.InvariantCulture),
        interval.ToString(CultureInfo.InvariantCulture));
    int items = AddNumericGroupItems(group, start, end, interval);
    AddFieldItems(items);

    _grouping = group;
    return group;
  }

  private int AddNumericGroupItems(
      ExcelPivotTableFieldNumericGroup group,
      double start,
      double end,
      double interval) {
    if (interval < 0) {
      throw (new("The interval must be a positiv"));
    }
    if (start > end) {
      throw (new("Then End number must be larger than the Start number"));
    }

    XmlElement groupItems =
        group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager)
            as XmlElement;
    int items = 2;
    //First date
    double index = start;
    double nextIndex = start + interval;
    AddGroupItem(groupItems, "<" + start.ToString(CultureInfo.InvariantCulture));

    while (index < end) {
      AddGroupItem(
          groupItems,
          string.Format(
              "{0}-{1}",
              index.ToString(CultureInfo.InvariantCulture),
              nextIndex.ToString(CultureInfo.InvariantCulture)));
      index = nextIndex;
      nextIndex += interval;
      items++;
    }
    AddGroupItem(groupItems, ">" + nextIndex.ToString(CultureInfo.InvariantCulture));
    return items;
  }

  private void AddFieldItems(int items) {
    XmlElement prevNode = null;
    XmlElement itemsNode = TopNode.SelectSingleNode("d:items", NameSpaceManager) as XmlElement;
    for (int x = 0; x < items; x++) {
      var itemNode = itemsNode.OwnerDocument.CreateElement("item", ExcelPackage._schemaMain);
      itemNode.SetAttribute("x", x.ToString());
      if (prevNode == null) {
        itemsNode.PrependChild(itemNode);
      } else {
        itemsNode.InsertAfter(itemNode, prevNode);
      }
      prevNode = itemNode;
    }
    itemsNode.SetAttribute("count", (items + 1).ToString());
  }

  private int AddDateGroupItems(
      ExcelPivotTableFieldGroup group,
      eDateGroupBy groupBy,
      DateTime startDate,
      DateTime endDate,
      int interval) {
    XmlElement groupItems =
        group.TopNode.SelectSingleNode("d:fieldGroup/d:groupItems", group.NameSpaceManager)
            as XmlElement;
    int items = 2;
    //First date
    AddGroupItem(
        groupItems,
        "<" + startDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));

    switch (groupBy) {
      case eDateGroupBy.Seconds:
      case eDateGroupBy.Minutes:
        AddTimeSerie(60, groupItems);
        items += 60;
        break;
      case eDateGroupBy.Hours:
        AddTimeSerie(24, groupItems);
        items += 24;
        break;
      case eDateGroupBy.Days:
        if (interval == 1) {
          DateTime dt = new DateTime(2008, 1, 1); //pick a year with 366 days
          while (dt.Year == 2008) {
            AddGroupItem(groupItems, dt.ToString("dd-MMM"));
            dt = dt.AddDays(1);
          }
          items += 366;
        } else {
          DateTime dt = startDate;
          items = 0;
          while (dt < endDate) {
            AddGroupItem(groupItems, dt.ToString("dd-MMM"));
            dt = dt.AddDays(interval);
            items++;
          }
        }
        break;
      case eDateGroupBy.Months:
        AddGroupItem(groupItems, "jan");
        AddGroupItem(groupItems, "feb");
        AddGroupItem(groupItems, "mar");
        AddGroupItem(groupItems, "apr");
        AddGroupItem(groupItems, "may");
        AddGroupItem(groupItems, "jun");
        AddGroupItem(groupItems, "jul");
        AddGroupItem(groupItems, "aug");
        AddGroupItem(groupItems, "sep");
        AddGroupItem(groupItems, "oct");
        AddGroupItem(groupItems, "nov");
        AddGroupItem(groupItems, "dec");
        items += 12;
        break;
      case eDateGroupBy.Quarters:
        AddGroupItem(groupItems, "Qtr1");
        AddGroupItem(groupItems, "Qtr2");
        AddGroupItem(groupItems, "Qtr3");
        AddGroupItem(groupItems, "Qtr4");
        items += 4;
        break;
      case eDateGroupBy.Years:
        if (startDate.Year >= 1900 && endDate != DateTime.MaxValue) {
          for (int year = startDate.Year; year <= endDate.Year; year++) {
            AddGroupItem(groupItems, year.ToString());
          }
          items += endDate.Year - startDate.Year + 1;
        }
        break;
      default:
        throw (new("unsupported grouping"));
    }

    //Lastdate
    AddGroupItem(
        groupItems,
        ">" + endDate.ToString("s", CultureInfo.InvariantCulture).Substring(0, 10));
    return items;
  }

  private void AddTimeSerie(int count, XmlElement groupItems) {
    for (int i = 0; i < count; i++) {
      AddGroupItem(groupItems, string.Format("{0:00}", i));
    }
  }

  private void AddGroupItem(XmlElement groupItems, string value) {
    var s = groupItems.OwnerDocument.CreateElement("s", ExcelPackage._schemaMain);
    s.SetAttribute("v", value);
    groupItems.AppendChild(s);
  }

  internal ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> _items;

  /// <summary>
  /// Pivottable field Items. Used for grouping.
  /// </summary>
  public ExcelPivotTableFieldCollectionBase<ExcelPivotTableFieldItem> Items {
    get {
      if (_items == null) {
        _items = new(_table);
        foreach (XmlNode node in TopNode.SelectNodes("d:items//d:item", NameSpaceManager)) {
          var item = new ExcelPivotTableFieldItem(NameSpaceManager, node, this);
          if (item.T == "") {
            _items.AddInternal(item);
          }
        }
        //if (_grouping is ExcelPivotTableFieldDateGroup)
        //{
        //    ExcelPivotTableFieldDateGroup dtgrp = ((ExcelPivotTableFieldDateGroup)_grouping);

        //    ExcelPivotTableFieldItem minItem=null, maxItem=null;
        //    foreach (var item in _items)
        //    {
        //        if (item.X == 0)
        //        {
        //            minItem = item;
        //        }
        //        else if (maxItem == null || maxItem.X < item.X)
        //        {
        //            maxItem = item;
        //        }
        //    }
        //    if (dtgrp.AutoStart)
        //    {
        //        _items._list.Remove(minItem);
        //    }
        //    if (dtgrp.AutoEnd)
        //    {
        //        _items._list.Remove(maxItem);
        //    }

        //}
      }
      return _items;
    }
  }

  /// <summary>
  /// Add numberic grouping to the field
  /// </summary>
  /// <param name="start">Start value</param>
  /// <param name="end">End value</param>
  /// <param name="interval">Interval</param>
  public void AddNumericGrouping(double start, double end, double interval) {
    ValidateGrouping();
    SetNumericGroup(start, end, interval);
  }

  /// <summary>
  /// Add a date grouping on this field.
  /// </summary>
  /// <param name="groupBy">Group by</param>
  public void AddDateGrouping(eDateGroupBy groupBy) {
    AddDateGrouping(groupBy, DateTime.MinValue, DateTime.MaxValue, 1);
  }

  /// <summary>
  /// Add a date grouping on this field.
  /// </summary>
  /// <param name="groupBy">Group by</param>
  /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
  /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
  public void AddDateGrouping(eDateGroupBy groupBy, DateTime startDate, DateTime endDate) {
    AddDateGrouping(groupBy, startDate, endDate, 1);
  }

  /// <summary>
  /// Add a date grouping on this field.
  /// </summary>
  /// <param name="days">Number of days when grouping on days</param>
  /// <param name="startDate">Fixed start date. Use DateTime.MinValue for auto</param>
  /// <param name="endDate">Fixed end date. Use DateTime.MaxValue for auto</param>
  public void AddDateGrouping(int days, DateTime startDate, DateTime endDate) {
    AddDateGrouping(eDateGroupBy.Days, startDate, endDate, days);
  }

  private void AddDateGrouping(
      eDateGroupBy groupBy,
      DateTime startDate,
      DateTime endDate,
      int groupInterval) {
    if (groupInterval < 1 || groupInterval >= Int16.MaxValue) {
      throw (new ArgumentOutOfRangeException("Group interval is out of range"));
    }
    if (groupInterval > 1 && groupBy != eDateGroupBy.Days) {
      throw (new ArgumentException("Group interval is can only be used when groupBy is Days"));
    }
    ValidateGrouping();

    bool firstField = true;
    List<ExcelPivotTableField> fields = new List<ExcelPivotTableField>();
    //Seconds
    if ((groupBy & eDateGroupBy.Seconds) == eDateGroupBy.Seconds) {
      fields.Add(AddField(eDateGroupBy.Seconds, startDate, endDate, ref firstField));
    }
    //Minutes
    if ((groupBy & eDateGroupBy.Minutes) == eDateGroupBy.Minutes) {
      fields.Add(AddField(eDateGroupBy.Minutes, startDate, endDate, ref firstField));
    }
    //Hours
    if ((groupBy & eDateGroupBy.Hours) == eDateGroupBy.Hours) {
      fields.Add(AddField(eDateGroupBy.Hours, startDate, endDate, ref firstField));
    }
    //Days
    if ((groupBy & eDateGroupBy.Days) == eDateGroupBy.Days) {
      fields.Add(AddField(eDateGroupBy.Days, startDate, endDate, ref firstField, groupInterval));
    }
    //Month
    if ((groupBy & eDateGroupBy.Months) == eDateGroupBy.Months) {
      fields.Add(AddField(eDateGroupBy.Months, startDate, endDate, ref firstField));
    }
    //Quarters
    if ((groupBy & eDateGroupBy.Quarters) == eDateGroupBy.Quarters) {
      fields.Add(AddField(eDateGroupBy.Quarters, startDate, endDate, ref firstField));
    }
    //Years
    if ((groupBy & eDateGroupBy.Years) == eDateGroupBy.Years) {
      fields.Add(AddField(eDateGroupBy.Years, startDate, endDate, ref firstField));
    }

    if (fields.Count > 1) {
      _cacheFieldHelper.SetXmlNodeString("d:fieldGroup/@par", (_table.Fields.Count - 1).ToString());
    }
    if (groupInterval != 1) {
      _cacheFieldHelper.SetXmlNodeString(
          "d:fieldGroup/d:rangePr/@groupInterval",
          groupInterval.ToString());
    } else {
      _cacheFieldHelper.DeleteNode("d:fieldGroup/d:rangePr/@groupInterval");
    }
    _items = null;
  }

  private void ValidateGrouping() {
    if (!(IsColumnField || IsRowField)) {
      throw (new("Field must be a row or column field"));
    }
    foreach (var field in _table.Fields) {
      if (field.Grouping != null) {
        throw (new("Grouping already exists"));
      }
    }
  }

  private ExcelPivotTableField AddField(
      eDateGroupBy groupBy,
      DateTime startDate,
      DateTime endDate,
      ref bool firstField) {
    return AddField(groupBy, startDate, endDate, ref firstField, 1);
  }

  private ExcelPivotTableField AddField(
      eDateGroupBy groupBy,
      DateTime startDate,
      DateTime endDate,
      ref bool firstField,
      int interval) {
    if (firstField == false) {
      //Pivot field
      var topNode = _table.PivotTableXml.SelectSingleNode(
          "//d:pivotFields",
          _table.NameSpaceManager);
      var fieldNode = _table.PivotTableXml.CreateElement("pivotField", ExcelPackage._schemaMain);
      fieldNode.SetAttribute("compact", "0");
      fieldNode.SetAttribute("outline", "0");
      fieldNode.SetAttribute("showAll", "0");
      fieldNode.SetAttribute("defaultSubtotal", "0");
      topNode.AppendChild(fieldNode);

      var field = new ExcelPivotTableField(
          _table.NameSpaceManager,
          fieldNode,
          _table,
          _table.Fields.Count,
          Index);
      field.DateGrouping = groupBy;

      XmlNode rowColFields;
      if (IsRowField) {
        rowColFields = TopNode.SelectSingleNode("../../d:rowFields", NameSpaceManager);
      } else {
        rowColFields = TopNode.SelectSingleNode("../../d:colFields", NameSpaceManager);
      }

      int fieldIndex,
          index = 0;
      foreach (XmlElement rowfield in rowColFields.ChildNodes) {
        if (int.TryParse(rowfield.GetAttribute("x"), out fieldIndex)) {
          if (_table.Fields[fieldIndex].BaseIndex == BaseIndex) {
            var newElement = rowColFields.OwnerDocument.CreateElement(
                "field",
                ExcelPackage._schemaMain);
            newElement.SetAttribute("x", field.Index.ToString());
            rowColFields.InsertBefore(newElement, rowfield);
            break;
          }
        }
        index++;
      }

      if (IsRowField) {
        _table.RowFields.Insert(field, index);
      } else {
        _table.ColumnFields.Insert(field, index);
      }

      _table.Fields.AddInternal(field);

      AddCacheField(field, startDate, endDate, interval);
      return field;
    }
    firstField = false;
    DateGrouping = groupBy;
    Compact = false;
    SetDateGroup(groupBy, startDate, endDate, interval);
    return this;
  }

  private void AddCacheField(
      ExcelPivotTableField field,
      DateTime startDate,
      DateTime endDate,
      int interval) {
    //Add Cache definition field.
    var cacheTopNode = _table.CacheDefinition.CacheDefinitionXml.SelectSingleNode(
        "//d:cacheFields",
        _table.NameSpaceManager);
    var cacheFieldNode = _table.CacheDefinition.CacheDefinitionXml.CreateElement(
        "cacheField",
        ExcelPackage._schemaMain);

    cacheFieldNode.SetAttribute("name", field.DateGrouping.ToString());
    cacheFieldNode.SetAttribute("databaseField", "0");
    cacheTopNode.AppendChild(cacheFieldNode);
    field.SetCacheFieldNode(cacheFieldNode);

    field.SetDateGroup(field.DateGrouping, startDate, endDate, interval);
  }
}
