// Code generated by tools/cmd/genjwa/main.go. DO NOT EDIT.

package jwa

import (
	"encoding/json"
	"fmt"
)

func init() {
	// builtin values for SignatureAlgorithm
	algorithms := make([]SignatureAlgorithm, 16)
	algorithms[0] = NewSignatureAlgorithm("ES256")
	algorithms[1] = NewSignatureAlgorithm("ES256K")
	algorithms[2] = NewSignatureAlgorithm("ES384")
	algorithms[3] = NewSignatureAlgorithm("ES512")
	algorithms[4] = NewSignatureAlgorithm("EdDSA", WithDeprecated(true))
	algorithms[5] = NewSignatureAlgorithm("Ed25519")
	algorithms[6] = NewSignatureAlgorithm("HS256", WithIsSymmetric(true))
	algorithms[7] = NewSignatureAlgorithm("HS384", WithIsSymmetric(true))
	algorithms[8] = NewSignatureAlgorithm("HS512", WithIsSymmetric(true))
	algorithms[9] = NewSignatureAlgorithm("none")
	algorithms[10] = NewSignatureAlgorithm("PS256")
	algorithms[11] = NewSignatureAlgorithm("PS384")
	algorithms[12] = NewSignatureAlgorithm("PS512")
	algorithms[13] = NewSignatureAlgorithm("RS256")
	algorithms[14] = NewSignatureAlgorithm("RS384")
	algorithms[15] = NewSignatureAlgorithm("RS512")

	RegisterSignatureAlgorithm(algorithms...)
	for _, alg := range algorithms {
		markBuiltin(alg.String())
	}
}

// ES256 returns an object representing ECDSA signature algorithm using P-256 curve and SHA-256.
func ES256() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("ES256")
}

// ES256K returns an object representing ECDSA signature algorithm using secp256k1 curve and SHA-256.
func ES256K() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("ES256K")
}

// ES384 returns an object representing ECDSA signature algorithm using P-384 curve and SHA-384.
func ES384() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("ES384")
}

// ES512 returns an object representing ECDSA signature algorithm using P-521 curve and SHA-512.
func ES512() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("ES512")
}

// EdDSA returns an object representing EdDSA signature algorithms (deprecated by RFC 9864, use EdDSAEd25519 or EdDSAEd448).
func EdDSA() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("EdDSA")
}

// EdDSAEd25519 returns an object representing EdDSA signature algorithm using Ed25519 (RFC 9864). The function name is tentative and may change in future releases.
func EdDSAEd25519() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("Ed25519")
}

// HS256 returns an object representing HMAC signature algorithm using SHA-256.
func HS256() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("HS256")
}

// HS384 returns an object representing HMAC signature algorithm using SHA-384.
func HS384() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("HS384")
}

// HS512 returns an object representing HMAC signature algorithm using SHA-512.
func HS512() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("HS512")
}

// NoSignature returns an object representing the lack of a signature algorithm. Using this value specifies that the content should not be signed, which you should avoid doing.
func NoSignature() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("none")
}

// PS256 returns an object representing RSASSA-PSS signature algorithm using SHA-256 and MGF1-SHA256.
func PS256() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("PS256")
}

// PS384 returns an object representing RSASSA-PSS signature algorithm using SHA-384 and MGF1-SHA384.
func PS384() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("PS384")
}

// PS512 returns an object representing RSASSA-PSS signature algorithm using SHA-512 and MGF1-SHA512.
func PS512() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("PS512")
}

// RS256 returns an object representing RSASSA-PKCS-v1.5 signature algorithm using SHA-256.
func RS256() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("RS256")
}

// RS384 returns an object representing RSASSA-PKCS-v1.5 signature algorithm using SHA-384.
func RS384() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("RS384")
}

// RS512 returns an object representing RSASSA-PKCS-v1.5 signature algorithm using SHA-512.
func RS512() SignatureAlgorithm {
	return lookupBuiltinSignatureAlgorithm("RS512")
}

func lookupBuiltinSignatureAlgorithm(name string) SignatureAlgorithm {
	v, ok := lookupAlgorithm(algKindSignature, name)
	if !ok {
		panic(fmt.Sprintf(`jwa: SignatureAlgorithm %q not registered`, name))
	}
	return v.(SignatureAlgorithm)
}

// SignatureAlgorithm represents the various signature algorithms as described in https://tools.ietf.org/html/rfc7518#section-3.1
type SignatureAlgorithm struct {
	name        string
	deprecated  bool
	isSymmetric bool
}

func (s SignatureAlgorithm) String() string {
	return s.name
}

// IsDeprecated returns true if the SignatureAlgorithm object is deprecated.
func (s SignatureAlgorithm) IsDeprecated() bool {
	return s.deprecated
}

// IsSymmetric returns true if the SignatureAlgorithm object is symmetric. Symmetric algorithms use the same key for both encryption and decryption.
func (s SignatureAlgorithm) IsSymmetric() bool {
	return s.isSymmetric
}

// EmptySignatureAlgorithm returns an empty SignatureAlgorithm object, used as a zero value.
func EmptySignatureAlgorithm() SignatureAlgorithm {
	return SignatureAlgorithm{}
}

// NewSignatureAlgorithm creates a new SignatureAlgorithm object with the given name.
func NewSignatureAlgorithm(name string, options ...NewSignatureAlgorithmOption) SignatureAlgorithm {
	var deprecated bool
	var isSymmetric bool
	for _, option := range options {
		switch option.Ident() {
		case identIsSymmetric{}:
			if err := option.Value(&isSymmetric); err != nil {
				panic("jwa.NewSignatureAlgorithm: WithIsSymmetric option must be a boolean")
			}
		case identDeprecated{}:
			if err := option.Value(&deprecated); err != nil {
				panic("jwa.NewSignatureAlgorithm: WithDeprecated option must be a boolean")
			}
		}
	}
	return SignatureAlgorithm{name: name, deprecated: deprecated, isSymmetric: isSymmetric}
}

// LookupSignatureAlgorithm returns the SignatureAlgorithm object for the given name.
func LookupSignatureAlgorithm(name string) (SignatureAlgorithm, bool) {
	if v, ok := lookupAlgorithm(algKindSignature, name); ok {
		return v.(SignatureAlgorithm), true
	}
	var zero SignatureAlgorithm
	return zero, false
}

// RegisterSignatureAlgorithm registers a new SignatureAlgorithm. The signature value must be immutable
// and safe to be used by multiple goroutines, as it is going to be shared with all other users of this library.
//
// Registration is process-global. Built-in identifiers such as RS256 are
// reserved and cannot be replaced by callers after init has completed; use a
// distinct name for third-party algorithms.
//
// SignatureAlgorithm, KeyEncryptionAlgorithm, and ContentEncryptionAlgorithm
// share a single algorithm-name namespace so that KeyAlgorithmFrom can
// resolve unambiguously. Registering a name that is already registered as a
// different kind is a silent no-op (the first Register* call wins).
func RegisterSignatureAlgorithm(algorithms ...SignatureAlgorithm) {
	for _, alg := range algorithms {
		registerAlgorithm(algKindSignature, alg)
	}
}

// UnregisterSignatureAlgorithm unregisters a SignatureAlgorithm from its known database.
// Non-existent entries, as well as built-in algorithms will silently be ignored.
func UnregisterSignatureAlgorithm(algorithms ...SignatureAlgorithm) {
	for _, alg := range algorithms {
		unregisterAlgorithm(algKindSignature, alg.String())
	}
}

// SignatureAlgorithms returns a list of all available values for SignatureAlgorithm.
func SignatureAlgorithms() []SignatureAlgorithm {
	raw := listAlgorithmsByKind(algKindSignature)
	out := make([]SignatureAlgorithm, len(raw))
	for i, alg := range raw {
		out[i] = alg.(SignatureAlgorithm)
	}
	return out
}

// MarshalJSON serializes the SignatureAlgorithm object to a JSON string.
func (s SignatureAlgorithm) MarshalJSON() ([]byte, error) {
	return json.Marshal(s.String())
}

// UnmarshalJSON deserializes the JSON string to a SignatureAlgorithm object.
func (s *SignatureAlgorithm) UnmarshalJSON(data []byte) error {
	var name string
	if err := json.Unmarshal(data, &name); err != nil {
		return fmt.Errorf(`failed to unmarshal SignatureAlgorithm: %w`, err)
	}
	v, ok := LookupSignatureAlgorithm(name)
	if !ok {
		return fmt.Errorf(`unknown SignatureAlgorithm: %q`, name)
	}
	*s = v
	return nil
}
