using System;
using System.Collections.Generic;

namespace OfficeOpenXml;

/// <summary>
/// Represents the errortypes in excel
/// </summary>
public enum eErrorType {
  /// <summary>
  /// Division by zero
  /// </summary>
  Div0,

  /// <summary>
  /// Not applicable
  /// </summary>
  Na,

  /// <summary>
  /// Name error
  /// </summary>
  Name,

  /// <summary>
  /// Null error
  /// </summary>
  Null,

  /// <summary>
  /// Num error
  /// </summary>
  Num,

  /// <summary>
  /// Reference error
  /// </summary>
  Ref,

  /// <summary>
  /// Value error
  /// </summary>
  Value,

  // Bug G0004
  /// <summary>
  /// Error error  // Google Bug G0004
  /// </summary>
  Error,

  // Bug G0005
  /// <summary>
  /// ErrorValueIsNullOrEmpty error  // Google Bug G0005
  /// </summary>
  ErrorValueIsNullOrEmpty,
}

/// <summary>
/// Represents an Excel error.
/// </summary>
/// <seealso cref="eErrorType"/>
public class ExcelErrorValue {
  /// <summary>
  /// Handles the convertion between <see cref="eErrorType"/> and the string values
  /// used by Excel.
  /// </summary>
  public static class Values {
    public const string Div0 = "#DIV/0!";
    public const string Na = "#N/A";
    public const string Name = "#NAME?";
    public const string Null = "#NULL!";
    public const string Num = "#NUM!";
    public const string Ref = "#REF!";
    public const string Value = "#VALUE!";
    public const string Error = "#ERROR!"; // Bug G0004
    public const string ErrorValueIsNullOrEmpty = "#ERRORVALUEISNULLOREMPTY!"; // Bug G0005

    private static readonly Dictionary<string, eErrorType> _values = new() {
      { Div0, eErrorType.Div0 },
      { Na, eErrorType.Na },
      { Name, eErrorType.Name },
      { Null, eErrorType.Null },
      { Num, eErrorType.Num },
      { Ref, eErrorType.Ref },
      { Value, eErrorType.Value },
      { Error, eErrorType.Error }, // Bug G0004
      {
        ErrorValueIsNullOrEmpty,
        eErrorType.ErrorValueIsNullOrEmpty
      } // Bug G0005
      ,
    };

    /// <summary>
    /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
    /// </summary>
    /// <param name="candidate"></param>
    /// <returns></returns>
    public static bool IsErrorValue(object candidate) {
      if (candidate == null || !(candidate is ExcelErrorValue)) {
        return false;
      }
      var candidateString = candidate.ToString();
      return (!string.IsNullOrEmpty(candidateString) && _values.ContainsKey(candidateString));
    }

    /// <summary>
    /// Returns true if the supplied <paramref name="candidate"/> is an excel error.
    /// </summary>
    /// <param name="candidate"></param>
    /// <returns></returns>
    public static bool StringIsErrorValue(string candidate) {
      return (!string.IsNullOrEmpty(candidate) && _values.ContainsKey(candidate));
    }

    /// <summary>
    /// Converts a string to an <see cref="eErrorType"/>
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException">Thrown if the supplied value is not an Excel error</exception>
    public static eErrorType ToErrorType(string val) {
      if (string.IsNullOrEmpty(val) || !_values.ContainsKey(val)) {
        throw new ArgumentException("Invalid error code " + (val ?? "<empty>"));
      }
      return _values[val];
    }
  }

  internal static ExcelErrorValue Create(eErrorType errorType) {
    return new(errorType);
  }

  internal static ExcelErrorValue Parse(string val) {
    if (string.IsNullOrEmpty(
        val)) // Google Bug G0005
    {
      val = Values.ErrorValueIsNullOrEmpty;
    }

    if (Values.StringIsErrorValue(val)) {
      return new(Values.ToErrorType(val));
    }
    if (string.IsNullOrEmpty(val)) {
      throw new ArgumentNullException("val");
    }
    throw new ArgumentException("Not a valid error value: " + val);
  }

  private ExcelErrorValue(eErrorType type) {
    Type = type;
  }

  /// <summary>
  /// The error type
  /// </summary>
  public eErrorType Type { get; private set; }

  /// <summary>
  /// Returns the string representation of the error type
  /// </summary>
  /// <returns></returns>
  public override string ToString() {
    switch (Type) {
      case eErrorType.Div0:
        return Values.Div0;
      case eErrorType.Na:
        return Values.Na;
      case eErrorType.Name:
        return Values.Name;
      case eErrorType.Null:
        return Values.Null;
      case eErrorType.Num:
        return Values.Num;
      case eErrorType.Ref:
        return Values.Ref;
      case eErrorType.Value:
        return Values.Value;
      case eErrorType.Error: // Bug G0004
        return Values.Error;
      case eErrorType.ErrorValueIsNullOrEmpty: // Bug G0005
        return Values.ErrorValueIsNullOrEmpty;
      default:
        throw (new ArgumentException("Invalid errortype"));
    }
  }

  public static ExcelErrorValue operator +(object v1, ExcelErrorValue v2) {
    return v2;
  }

  public static ExcelErrorValue operator +(ExcelErrorValue v1, ExcelErrorValue v2) {
    return v1;
  }

  public override int GetHashCode() {
    return base.GetHashCode();
  }

  public override bool Equals(object obj) {
    if (!(obj is ExcelErrorValue value)) {
      return false;
    }
    return value.ToString() == ToString();
  }
}
