package random

import (
	cryptorand "crypto/rand"
	"encoding/base64"
	mathrand "math/rand"
)

// RandAlphaNumeric generates a random alphanumeric string of specified length.
//
// Parameters:
//
//	size int - the length of the string to generate.
//
// Returns:
//
//	string - the randomly generated alphanumeric string.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randAlphaNum].
//
// [Sprout Documentation: randAlphaNum]: https://docs.atom.codes/sprout/registries/random#randalphanum
func (rr *RandomRegistry) RandAlphaNumeric(size int) string {
	return rr.randomString(size, &randomOpts{withLetters: true, withNumbers: true})
}

// RandAlpha generates a random alphabetic string of specified length.
//
// Parameters:
//
//	size int - the length of the string to generate.
//
// Returns:
//
//	string - the randomly generated alphabetic string.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randAlpha].
//
// [Sprout Documentation: randAlpha]: https://docs.atom.codes/sprout/registries/random#randalpha
func (rr *RandomRegistry) RandAlpha(size int) string {
	return rr.randomString(size, &randomOpts{withLetters: true})
}

// RandAscii generates a random ASCII string (character codes 32 to 126) of specified length.
//
// Parameters:
//
//	size int - the length of the string to generate.
//
// Returns:
//
//	string - the randomly generated ASCII string.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randAscii].
//
// [Sprout Documentation: randAscii]: https://docs.atom.codes/sprout/registries/random#randascii
func (rr *RandomRegistry) RandAscii(size int) string {
	return rr.randomString(size, &randomOpts{withAscii: true})
}

// RandNumeric generates a random numeric string of specified length.
//
// Parameters:
//
//	size int - the length of the string to generate.
//
// Returns:
//
//	string - the randomly generated numeric string.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randNumeric].
//
// [Sprout Documentation: randNumeric]: https://docs.atom.codes/sprout/registries/random#randnumeric
func (rr *RandomRegistry) RandNumeric(size int) string {
	return rr.randomString(size, &randomOpts{withNumbers: true})
}

// RandBytes generates a random byte array of specified length and returns it as a base64 encoded string.
//
// Parameters:
//
//	size int - the number of bytes to generate.
//
// Returns:
//
//	string - the base64 encoded string of the randomly generated bytes.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randBytes].
//
// [Sprout Documentation: randBytes]: https://docs.atom.codes/sprout/registries/random#randbytes
func (rr *RandomRegistry) RandBytes(size int) (string, error) {
	if size <= 0 {
		return "", nil
	}

	buf := make([]byte, size)
	_, err := cryptorand.Read(buf)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(buf), nil
}

// RandInt generates a random integer between the specified minimum and maximum
// values (inclusive).
//
// Parameters:
// - min: the minimum value of the range (inclusive).
// - max: the maximum value of the range (inclusive).
//
// Returns:
// - int: the randomly generated integer.
//
// For an example of this function in a Go template, refer to [Sprout Documentation: randInt].
//
// [Sprout Documentation: randInt]: https://docs.atom.codes/sprout/registries/random#randint
func (rr *RandomRegistry) RandInt(min, max int) int {
	return mathrand.Intn(max-min) + min
}
