using System;
using System.Collections.Generic;

namespace AppsheetEpplus;

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