
/*

represent arbitrary bytes as human readable names, looks like:

	Xotemu Jaycifmur
	Oleoti Eweuhipag
	Tinewe Uyoaluafi

every three letters is a syllable, which represents one byte.

*/

import {Bytes} from "../bytes.js"
import {syllables} from "./utils/syllables.js"

const dictionary = syllables.combo
const defaultPattern = "Xxxxxx Xxxxxxxxx "

/** @deprecated use `Urname` instead */
export const Bytename = {
	dictionary,

	string(bytes: Uint8Array, pattern = defaultPattern) {
		if (pattern.indexOf("x") === -1)
			throw new Error("invalid pattern")

		const parts: string[] = []
		for (const byte of bytes)
			parts.push(dictionary.at(byte)!)

		const composite = [...parts.join("")].toReversed()
		const letters: string[] = []
		let patternIndex = 0

		while (composite.length > 0) {
			const glyph = pattern.at(patternIndex % pattern.length)!
			letters.push(
				glyph === "x" ?
					composite.pop()! :
				glyph === "X" ?
					composite.pop()!.toUpperCase() :
					glyph
			)
			patternIndex++
		}

		return letters.join("")
	},

	bytes(string: string) {
		const letters = string.toLowerCase().trim().replace(/\s+/g, "")
		const count = letters.length / 3
		if ((count % 1) !== 0)
			throw new Error(`invalid triplet count, ${letters.length} does not divide into triplets`)

		const triplets: string[] = []
		for (const index of Array(count).keys()) {
			const i = index * 3
			triplets.push(letters[i] + letters[i + 1] + letters[i + 2])
		}

		return new Uint8Array(triplets.map(triplet => {
			const number = dictionary.findIndex(t => t === triplet)
			if (number === -1)
				throw new Error(`unknown triplet ${triplet}`)
			return number
		}))
	},

	equal(name1: string, name2: string) {
		const re1 = this.string(this.bytes(name1), "x")
		const re2 = this.string(this.bytes(name2), "x")
		return re1 === re2
	},

	/** generate a random bytename. byteCount defaults to 5. */
	random(byteCount = 5, pattern = defaultPattern) {
		return this.string(Bytes.random(byteCount), pattern)
	},
}

