const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='

function toUtf8Bytes(text) {
	let out = ''
	const normalized = String(text).replace(/\r\n/g, '\n')
	for (let i = 0; i < normalized.length; i++) {
		const code = normalized.charCodeAt(i)
		if (code < 128) {
			out += String.fromCharCode(code)
		} else if (code < 2048) {
			out += String.fromCharCode((code >> 6) | 192, (code & 63) | 128)
		} else {
			out += String.fromCharCode((code >> 12) | 224, ((code >> 6) & 63) | 128, (code & 63) | 128)
		}
	}
	return out
}

export default class Base64Codec {
	encode(plain) {
		const bytes = toUtf8Bytes(plain)
		let output = ''
		for (let i = 0; i < bytes.length;) {
			const c1 = bytes.charCodeAt(i++)
			const c2 = bytes.charCodeAt(i++)
			const c3 = bytes.charCodeAt(i++)
			const b1 = c1 >> 2
			const b2 = ((c1 & 3) << 4) | (isNaN(c2) ? 0 : c2 >> 4)
			const b3 = isNaN(c2) ? 64 : (((c2 & 15) << 2) | (isNaN(c3) ? 0 : c3 >> 6))
			const b4 = isNaN(c3) ? 64 : (c3 & 63)
			output += ALPHABET[b1] + ALPHABET[b2] + ALPHABET[b3] + ALPHABET[b4]
		}
		return output
	}
}
