/*******************************************************************************
 * 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.Collections.Immutable;
using System.Xml;

namespace AppsheetEpplus;

/// <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 readonly List<IExcelDataValidation> _validations = new();
  private readonly ExcelWorksheet _worksheet;

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

  protected override ImmutableArray<string> SchemaNodeOrder =>
    ExcelWorksheet.WorksheetSchemaNodeOrder;

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

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

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

  /// <summary>
  /// Validates address - not empty, collisions
  /// </summary>
  /// <param name="address"></param>
  /// <param name="validatingValidation"></param>
  private void ValidateAddress(string address, IExcelDataValidation validatingValidation) {
    ArgumentException.ThrowIfNullOrEmpty(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);
    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);
    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);
    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);
    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);
    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);
    return item;
  }

  public IExcelDataValidationTime AddTimeValidation(string address) {
    ValidateAddress(address);
    EnsureRootElementExists();
    var item = new ExcelDataValidationTime(_worksheet, address, ExcelDataValidationType.Time);
    _validations.Add(item);
    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);
    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 validation)) {
      throw new InvalidCastException(
          "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
    }
    ArgumentNullException.ThrowIfNull(item);
    TopNode.RemoveChild(validation.TopNode);
    return _validations.Remove(validation);
  }

  /// <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 => _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 validation)) {
        throw new InvalidCastException(
            "The supplied item must inherit OfficeOpenXml.DataValidation.ExcelDataValidation");
      }
      TopNode
          .SelectSingleNode(_dataValidationPath.TrimStart('/'), NameSpaceManager)
          .RemoveChild(validation.TopNode);
    }
    _validations.RemoveAll(match);
  }

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

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