/*******************************************************************************
 * 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
 * ******************************************************************************
 * Mats Alm   		                Added       		        2011-01-01
 * Mats Alm                         Applying patch submitted    2011-11-14
 *                                  by Ted Heatherington
 * Jan Källman		                License changed GPL-->LGPL  2011-12-27
 * Raziq York		                Added support for Any type  2014-08-08
*******************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using OfficeOpenXml.DataValidation.Contracts;
using OfficeOpenXml.Utils;

namespace OfficeOpenXml.DataValidation;

/// <summary>
/// <para>
/// Collection of <see cref="ExcelDataValidation"/>. This class is providing the API for EPPlus data validation.
/// </para>
/// <para>
/// The public methods of this class (Add[...]Validation) will create a datavalidation entry in the worksheet. When this
/// validation has been created changes to the properties will affect the workbook immediately.
/// </para>
/// <para>
/// Each type of validation has either a formula or a typed value/values, except for custom validation which has a formula only.
/// </para>
/// <code>
/// // Add a date time validation
/// var validation = worksheet.DataValidation.AddDateTimeValidation("A1");
/// // set validation properties
/// validation.ShowErrorMessage = true;
/// validation.ErrorTitle = "An invalid date was entered";
/// validation.Error = "The date must be between 2011-01-31 and 2011-12-31";
/// validation.Prompt = "Enter date here";
/// validation.Formula.Value = DateTime.Parse("2011-01-01");
/// validation.Formula2.Value = DateTime.Parse("2011-12-31");
/// validation.Operator = ExcelDataValidationOperator.between;
/// </code>
/// </summary>
public class ExcelDataValidationCollection : XmlHelper, IEnumerable<IExcelDataValidation> {
  private List<IExcelDataValidation> _validations = new();
  private ExcelWorksheet _worksheet;

  private const string _dataValidationPath = "//d:dataValidations";
  private readonly string DataValidationItemsPath = string.Format(
      "{0}/d:dataValidation",
      _dataValidationPath);

  /// <summary>
  /// Constructor
  /// </summary>
  /// <param name="worksheet"></param>
  internal ExcelDataValidationCollection(ExcelWorksheet worksheet)
      : base(worksheet.NameSpaceManager, worksheet.WorksheetXml.DocumentElement) {
    Require.Argument(worksheet).IsNotNull("worksheet");
    _worksheet = worksheet;
    SchemaNodeOrder = worksheet.SchemaNodeOrder;

    // check existing nodes and load them
    var dataValidationNodes = worksheet.WorksheetXml.SelectNodes(
        DataValidationItemsPath,
        worksheet.NameSpaceManager);
    if (dataValidationNodes != null && dataValidationNodes.Count > 0) {
      foreach (XmlNode node in dataValidationNodes) {
        if (node.Attributes["sqref"] == null) {
          continue;
        }

        var addr = node.Attributes["sqref"].Value;

        var typeSchema = node.Attributes["type"] != null ? node.Attributes["type"].Value : "";

        var type = ExcelDataValidationType.GetBySchemaName(typeSchema);
        _validations.Add(ExcelDataValidationFactory.Create(type, worksheet, addr, node));
      }
    }
    if (_validations.Count > 0) {
      OnValidationCountChanged();
    }
  }

  private void EnsureRootElementExists() {
    var node = _worksheet.WorksheetXml.SelectSingleNode(
        _dataValidationPath,
        _worksheet.NameSpaceManager);
    if (node == null) {
      CreateNode(_dataValidationPath.TrimStart('/'));
    }
  }

  private void OnValidationCountChanged() {
    //if (TopNode != null)
    //{
    //    SetXmlNodeString("@count", _validations.Count.ToString());
    //}
  }

  private XmlNode GetRootNode() {
    EnsureRootElementExists();
    TopNode = _worksheet.WorksheetXml.SelectSingleNode(
        _dataValidationPath,
        _worksheet.NameSpaceManager);
    return TopNode;
  }

  /// <summary>
  /// Validates address - not empty, collisions
  /// </summary>
  /// <param name="address"></param>
  /// <param name="validatingValidation"></param>
  private void ValidateAddress(string address, IExcelDataValidation validatingValidation) {
    Require.Argument(address).IsNotNullOrEmpty("address");

    // ensure that the new address does not collide with an existing validation.
    var newAddress = new ExcelAddress(address);
    if (_validations.Count > 0) {
      foreach (var validation in _validations) {
        if (validatingValidation != null && validatingValidation == validation) {
          continue;
        }
        var result = validation.Address.Collide(newAddress);
        if (result != ExcelAddressBase.eAddressCollition.No) {
          throw new InvalidOperationException(
              string.Format(
                  "The address ({0}) collides with an existing validation ({1})",
                  address,
                  validation.Address.Address));
        }
      }
    }
  }

  private void ValidateAddress(string address) {
    ValidateAddress(address, null);
  }

  /// <summary>
  /// Validates all data validations.
  /// </summary>
  internal void ValidateAll() {
    foreach (var validation in _validations) {
      validation.Validate();

      ValidateAddress(validation.Address.Address, validation);
    }
  }

  /// <summary>
  /// Adds a <see cref="ExcelDataValidationAny"/> to the worksheet.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationAny AddAnyValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationAny(_worksheet, address, ExcelDataValidationType.Any);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Adds an <see cref="IExcelDataValidationInt"/> to the worksheet. Whole means that the only accepted values
  /// are integer values.
  /// </summary>
  /// <param name="address">the range/address to validate</param>
  public IExcelDataValidationInt AddIntegerValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.Whole);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Addes an <see cref="IExcelDataValidationDecimal"/> to the worksheet. The only accepted values are
  /// decimal values.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationDecimal AddDecimalValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationDecimal(_worksheet, address, ExcelDataValidationType.Decimal);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Adds an <see cref="IExcelDataValidationList"/> to the worksheet. The accepted values are defined
  /// in a list.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationList AddListValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationList(_worksheet, address, ExcelDataValidationType.List);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Adds an <see cref="IExcelDataValidationInt"/> regarding text length to the worksheet.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationInt AddTextLengthValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationInt(_worksheet, address, ExcelDataValidationType.TextLength);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Adds an <see cref="IExcelDataValidationDateTime"/> to the worksheet.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationDateTime AddDateTimeValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationDateTime(
        _worksheet,
        address,
        ExcelDataValidationType.DateTime);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  public IExcelDataValidationTime AddTimeValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Adds a <see cref="ExcelDataValidationCustom"/> to the worksheet.
  /// </summary>
  /// <param name="address">The range/address to validate</param>
  /// <returns></returns>
  public IExcelDataValidationCustom AddCustomValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationCustom(_worksheet, address, ExcelDataValidationType.Custom);
    _validations.Add(item);
    OnValidationCountChanged();
    return item;
  }

  /// <summary>
  /// Removes an <see cref="ExcelDataValidation"/> from the collection.
  /// </summary>
  /// <param name="item">The item to remove</param>
  /// <returns>True if remove succeeds, otherwise false</returns>
  /// <exception cref="ArgumentNullException">if <paramref name="item"/> is null</exception>
  public bool Remove(IExcelDataValidation item) {
    if (!(item is ExcelDataValidation)) {
      throw new InvalidCastException(
          "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
    }
    Require.Argument(item).IsNotNull("item");
    TopNode.RemoveChild(((ExcelDataValidation)item).TopNode);
    var retVal = _validations.Remove(item);
    if (retVal) {
      OnValidationCountChanged();
    }
    return retVal;
  }

  /// <summary>
  /// Number of validations
  /// </summary>
  public int Count => _validations.Count;

  /// <summary>
  /// Index operator, returns by 0-based index
  /// </summary>
  /// <param name="index"></param>
  /// <returns></returns>
  public IExcelDataValidation this[int index] {
    get { return _validations[index]; }
    set { _validations[index] = value; }
  }

  /// <summary>
  /// Index operator, returns a data validation which address partly or exactly matches the searched address.
  /// </summary>
  /// <param name="address">A cell address or range</param>
  /// <returns>A <see cref="ExcelDataValidation"/> or null if no match</returns>
  public IExcelDataValidation this[string address] {
    get {
      var searchedAddress = new ExcelAddress(address);
      return _validations.Find(x =>
          x.Address.Collide(searchedAddress) != ExcelAddressBase.eAddressCollition.No);
    }
  }

  /// <summary>
  /// Returns all validations that matches the supplied predicate <paramref name="match"/>.
  /// </summary>
  /// <param name="match">predicate to filter out matching validations</param>
  /// <returns></returns>
  public IEnumerable<IExcelDataValidation> FindAll(Predicate<IExcelDataValidation> match) {
    return _validations.FindAll(match);
  }

  /// <summary>
  /// Returns the first matching validation.
  /// </summary>
  /// <param name="match"></param>
  /// <returns></returns>
  public IExcelDataValidation Find(Predicate<IExcelDataValidation> match) {
    return _validations.Find(match);
  }

  /// <summary>
  /// Removes all validations from the collection.
  /// </summary>
  public void Clear() {
    DeleteAllNode(DataValidationItemsPath.TrimStart('/'));
    _validations.Clear();
  }

  /// <summary>
  /// Removes the validations that matches the predicate
  /// </summary>
  /// <param name="match"></param>
  public void RemoveAll(Predicate<IExcelDataValidation> match) {
    var matches = _validations.FindAll(match);
    foreach (var m in matches) {
      if (!(m is ExcelDataValidation)) {
        throw new InvalidCastException(
            "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
      }
      TopNode
          .SelectSingleNode(_dataValidationPath.TrimStart('/'), NameSpaceManager)
          .RemoveChild(((ExcelDataValidation)m).TopNode);
    }
    _validations.RemoveAll(match);
    OnValidationCountChanged();
  }

  IEnumerator<IExcelDataValidation> IEnumerable<IExcelDataValidation>.GetEnumerator() {
    return _validations.GetEnumerator();
  }

  IEnumerator IEnumerable.GetEnumerator() {
    return _validations.GetEnumerator();
  }
}
