package util_test

import (
	"fmt"
	"math"
	"regexp"
	"strconv"
	"testing"
)

var re = regexp.MustCompile(`\d{2}$`)

// Get a masked value from a http status code (e.g. 201=2xx, 204=2xx, 405=4xx, 500=5xx)
func BenchmarkStatusBucket(b *testing.B) {
	statusCode := 201

	b.Run("if-statements", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusIfStatemets(statusCode)
			_ = s
		}
	})

	b.Run("Itoa+concat", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusItoaWithConcat(statusCode)
			_ = s
		}
	})

	b.Run("Itoa+[]byte", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusItoaWithByteArray(statusCode)
			_ = s
		}
	})

	b.Run("Itoa+Sprintf", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusItoaWithSprintf(statusCode)
			_ = s
		}
	})

	b.Run("regex+concat", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusRegexWithConcat(statusCode)
			_ = s
		}
	})

	b.Run("math+Sprintf", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			s := getStatusMathWithSprintf(statusCode)
			_ = s
		}
	})
}

var (
	status1xx = "1xx"
	status2xx = "2xx"
	status3xx = "3xx"
	status4xx = "4xx"
	status5xx = "5xx"
)

func getStatusIfStatemets(statusCode int) string {
	if statusCode >= 100 && statusCode < 200 {
		return status1xx
	} else if statusCode < 300 {
		return status2xx
	} else if statusCode < 400 {
		return status3xx
	} else if statusCode < 500 {
		return status4xx
	}

	return status5xx
}

func getStatusItoaWithConcat(statusCode int) string {
	return string(strconv.Itoa(statusCode)[0]) + "xx"
}

func getStatusItoaWithByteArray(statusCode int) string {
	b := make([]byte, 3)
	b[0] = strconv.Itoa(statusCode)[0]
	b[1] = 'x'
	b[2] = 'x'
	return string(b[:])
}
func getStatusItoaWithSprintf(statusCode int) string {
	return fmt.Sprintf("%dxx", strconv.Itoa(statusCode)[0])
}
func getStatusRegexWithConcat(statusCode int) string {
	return re.ReplaceAllString(strconv.FormatInt(int64(statusCode), 10), `XX`)
}
func getStatusMathWithSprintf(statusCode int) string {
	return fmt.Sprintf("%.0fxx", math.Floor(float64(statusCode/100)))
}