package set1

const Base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
const Base64PaddingCharacter = "="

// NOTE: Unused
func HexDecode(hex string) (value string, success bool) {
	size := len(hex)

	var hexValues = map[byte]byte{
		'0': 0,
		'1': 1,
		'2': 2,
		'3': 3,
		'4': 4,
		'5': 5,
		'6': 6,
		'7': 7,
		'8': 8,
		'9': 9,
		'a': 10,
		'b': 11,
		'c': 12,
		'd': 13,
		'e': 14,
		'f': 15,
	}

	if size%2 != 0 {
		return "", false
	}

	buffer := make([]byte, 0, size/2)

	for i := 0; i < size; i += 2 {
		first := hexValues[hex[i]] << 4
		second := hexValues[hex[i+1]]

		buffer = append(buffer, first^second)
	}

	return string(buffer), true
}

// NOTE: Unused
func Base64Encode(value string) (base64 string) {
	originalBytes := []byte(value)
	size := len(originalBytes)

	buffer := make([]byte, 0, size+size/3)

	for i := 0; i < size; i += 3 {

		// TODO: Handle end case to add padding

		originals := originalBytes[i : i+3]

		first := originals[0] >> 2
		second := (0b00110000 & (originals[0] << 4)) ^ (originals[1] >> 4)
		third := (0b00111100 & (originals[1] << 2)) ^ (originals[2] >> 6)
		fourth := 0b00111111 & originals[2]

		buffer = append(buffer, Base64Alphabet[first], Base64Alphabet[second], Base64Alphabet[third], Base64Alphabet[fourth])
	}

	return string(buffer)
}

func HexToBase64(hexValue string) (base64 string, success bool) {
	hexSize := len(hexValue)

	var hexValues = map[byte]byte{
		'0': 0,
		'1': 1,
		'2': 2,
		'3': 3,
		'4': 4,
		'5': 5,
		'6': 6,
		'7': 7,
		'8': 8,
		'9': 9,
		'a': 10,
		'b': 11,
		'c': 12,
		'd': 13,
		'e': 14,
		'f': 15,
	}

	if hexSize%2 != 0 {
		return "", false
	}

	plainBuffer := make([]byte, 0, hexSize/2)

	for i := 0; i < hexSize; i += 2 {
		first := hexValues[hexValue[i]] << 4
		second := hexValues[hexValue[i+1]]

		plainBuffer = append(plainBuffer, first^second)
	}

	plainSize := len(plainBuffer)

	base64Buffer := make([]byte, 0, plainSize+plainSize/3)

	for i := 0; i < plainSize; i += 3 {

		// TODO: Handle end case to add padding

		originals := plainBuffer[i : i+3]

		first := originals[0] >> 2
		second := (0b00110000 & (originals[0] << 4)) ^ (originals[1] >> 4)
		third := (0b00111100 & (originals[1] << 2)) ^ (originals[2] >> 6)
		fourth := 0b00111111 & originals[2]

		base64Buffer = append(base64Buffer, Base64Alphabet[first], Base64Alphabet[second], Base64Alphabet[third], Base64Alphabet[fourth])
	}

	return string(base64Buffer), true
}