// Copyright (C) 2018 Marius Schellenberger

package jwt

import (
	"crypto/sha256"
	"crypto/sha512"
	"hash"
)

const (
	HS256Name = "HS256"
	HS384Name = "HS384"
	HS512Name = "HS512"
)

// ParseHash returns the Hash type equal to the input string
func ParseHash(alg string) Hash {
	switch alg {
	case HS256Name:
		return NewHS256()
	case HS384Name:
		return NewHS384()
	case HS512Name:
		return NewHS512()
	}
	return nil
}

// Hash is the hashsum interface for signing the jwt
type Hash interface {
	Hash() hash.Hash
	Alg() string
}

// HS256 implements the Hash interface with SHA256
type HS256 struct{}

// NewHS256 returns a new HS256 instance
func NewHS256() Hash {
	return HS256{}
}

// Alg returns the algorithm name "HS256"
func (HS256) Alg() string {
	return HS256Name
}

// Hash returns a new hash.Hash instance of the SHA256 algorithm
func (HS256) Hash() hash.Hash {
	return sha256.New()
}

// HS384 implements the Hash interface with SHA384
type HS384 struct{}

// NewHS384 returns a new HS384 instance
func NewHS384() Hash {
	return HS384{}
}

// Alg returns the algorithm name "HS384"
func (HS384) Alg() string {
	return HS384Name
}

// Hash returns a new hash.Hash instance of the SHA384 algorithm
func (HS384) Hash() hash.Hash {
	return sha512.New384()
}

// HS512 implements the Hash interface with SHA512
type HS512 struct{}

// NewHS512 returns a new HS512 instance
func NewHS512() Hash {
	return HS512{}
}

// Alg returns the algorithm name "HS512"
func (HS512) Alg() string {
	return HS512Name
}

// Hash returns a new hash.Hash instance of the SHA512 algorithm
func (HS512) Hash() hash.Hash {
	return sha512.New()
}
