using System.Diagnostics.CodeAnalysis;
namespace System.Security.Cryptography
{
    
    public readonly struct HashAlgorithmName : IEquatable<HashAlgorithmName>
    {
        public static HashAlgorithmName MD5 { get { return new HashAlgorithmName("MD5"); } }
        public static HashAlgorithmName SHA1 { get { return new HashAlgorithmName("SHA1"); } }
        public static HashAlgorithmName SHA256 { get { return new HashAlgorithmName("SHA256"); } }
        public static HashAlgorithmName SHA384 { get { return new HashAlgorithmName("SHA384"); } }
        public static HashAlgorithmName SHA512 { get { return new HashAlgorithmName("SHA512"); } }
        public static HashAlgorithmName SHA3_256 => new HashAlgorithmName("SHA3-256");
        public static HashAlgorithmName SHA3_384 => new HashAlgorithmName("SHA3-384");
        public static HashAlgorithmName SHA3_512 => new HashAlgorithmName("SHA3-512");
        private readonly string? _name;
        public HashAlgorithmName(string? name)
        {
            // Note: No validation because we have to deal with default(HashAlgorithmName) regardless.
            _name = name;
        }
        public string? Name
        {
            get { return _name; }
        }
        public override string ToString()
        {
            return _name ?? string.Empty;
        }
        public override bool Equals([NotNullWhen(true)] object? obj)
        {
            return obj is HashAlgorithmName && Equals((HashAlgorithmName)obj);
        }
        public bool Equals(HashAlgorithmName other)
        {
            // NOTE: intentionally ordinal and case sensitive, matches CNG.
            return _name == other._name;
        }
        public override int GetHashCode()
        {
            return _name == null ? 0 : _name.GetHashCode();
        }
        public static bool operator ==(HashAlgorithmName left, HashAlgorithmName right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(HashAlgorithmName left, HashAlgorithmName right)
        {
            return !(left == right);
        }
        //其他扩展功能
        public static bool TryFromOid(string oidValue, out HashAlgorithmName value)
        {
            ArgumentNullException.ThrowIfNull(oidValue);
            switch (oidValue)
            {
                case Oids.Md5:
                    value = MD5;
                    return true;
                case Oids.Sha1:
                    value = SHA1;
                    return true;
                case Oids.Sha256:
                    value = SHA256;
                    return true;
                case Oids.Sha384:
                    value = SHA384;
                    return true;
                case Oids.Sha512:
                    value = SHA512;
                    return true;
                case Oids.Sha3_256:
                    value = SHA3_256;
                    return true;
                case Oids.Sha3_384:
                    value = SHA3_384;
                    return true;
                case Oids.Sha3_512:
                    value = SHA3_512;
                    return true;
                default:
                    value = default;
                    return false;
            }
        }
        public static HashAlgorithmName FromOid(string oidValue)
        {
            if (TryFromOid(oidValue, out HashAlgorithmName value))
            {
                return value;
            }
            throw new CryptographicException(SR.Format(SR.Cryptography_InvalidHashAlgorithmOid, oidValue));
        }
    }
}