#! /usr/bin/env bash
#
# alea
#
# Release: 1.0 of 2026/03/27
# 2026, Joseph Maillardet
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU  General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

set -euo pipefail

speed=".001"
ultra=false
emo=false; emo_generated=false
alea=false; alea_generated=false
color=false
unfix=false
selected_color=''
char='#'
cols=$(tput cols)
lines=$(tput lines)

# convert unicode point (\U0001F???) to UTF-8 hexa
# for s in $'\U0001F000' $'\U0001FFFF'
# python3 - <<EOF
# s = "$s"
# print(s.encode("utf-8").hex())
# EOF
emoji_1f=$'\xF0\x9F[\x80-\xBF][\x80-\xBF]' # Match emoji in UTF-8 Hex

gen_emo_tab() { # table with emoji collection
	emoji=(🀄 🃏 🌈 🌊 🌋 🌍 🌕 🌙 🌚 🌛 🌜 🌝 🌞 🌟 🌭 🌮 🌯 🌰 🌱 🌲 🌳 🌴 🌵\
	🌷 🌸 🌹 🌺 🌻 🌼 🌽 🌾 🌿 🍀 🍁 🍂 🍃 🍄 🍅 🍆 🍇 🍈 🍉 🍊 🍋 🍌 🍍 🍎 🍏 🍐\
	🍑 🍒 🍓 🍔 🍕 🍖 🍗 🍘 🍙 🍚 🍛 🍜 🍝 🍞 🍟 🍠 🍡 🍢 🍣 🍤 🍥 🍦 🍧 🍨 🍩 🍪\
	🍫 🍬 🍭 🍮 🍯 🍰 🍱 🍲 🍷 🍸 🍹 🍺 🍻 🍼 🍿 🎀 🎁 🎂 🎃 🎄 🎅 🎇 🎈	🎉 🎊 🎋\
	🎌 🎎 🎏 🎐 🎑 🎒 🎓 🎧 🎨 🎩 🎪 🎬 🎭 🎮 🎯 🎰 🎱 🎲 🎳 🏀 🏆 🏈 🏉 🏐 🏓 🐀\
	🐁 🐂 🐃 🐄 🐅 🐆 🐇 🐈 🐉 🐊 🐋 🐌 🐍 🐎 🐏 🐐 🐑 🐒 🐓 🐔 🐕 🐖 🐗 🐘 🐙 🐚\
	🐛 🐜 🐝 🐞 🐟 🐠 🐡 🐢 🐣 🐤 🐥 🐦 🐧 🐨 🐩 🐪 🐫 🐬 🐭 🐮 🐯 🐰 🐱 🐲 🐳 🐴\
	🐵 🐶 🐷 🐸 🐹 🐺 🐻 🐼 🐽 👀 👂 👃 👄 👅 👆 👇 👈 👉 ✊ 👊 👋 👌 👍 👎 👏 👐\
	👒 👕 👖 👗 👘 👙 👚 👛 👜 👝 👰 👱 👲 👳 👴 👵 👶 👷 👸 👹 👺 👻 👼 👽 👾 👿\
	💀 💁 💂 💎 💘 💙 💚 💛 👑 💝 💡 💣 💥 💩 💪 💫 🔑 🔥 🖕 🖖 🗿 😀 😁 😂 😃 😄\
	😅 😆 😇 😈 😉 😊 😋 😌 😍 😎 😏 😐 😑 😒 😓 😔 😕 😖 😗 😘 😙 😚 😛 😜 😝 😞\
	😟 😠 😡 😢 😣 😤 😥 😦 😧 😨 😩 😪 😫 😬 😭 😮 😯 😰 😱 😲 😳 😴 😵 😶 😷 😸\
	😹 😺 😻 😼 😽 😾 😿 🙀 🙁 🙂 🙃 🙄 🙅 🙆 🙇 🙈 🙉 🙊 🙋 🙌 🙍 🙎 🙏 🚀 🚐 🚑\
	🚒 🚓 🚔 🚕 🚖 🚗 🚘 🚙 🚚 🚛 🚜 🟠 🟡 🟢 🟣 🟤 🤌 🤍 🤎 🤏 🤐 🤑 🤒 🤓 🤔 🤕\
	🤖 🤗 🤘 🤙 🤚 🤛 🤜 🤝 🤞 🤟 🤠 🤡 🤢 🤣 🤤 🤥 🤦 🤧 🤨 🤩 🤪 🤫 🤬 🤭 🤮 🤯\
	🤱 🤲 🤳 🤴 🤵 🤶 🤷 🥎 🥏 🥐 🥑 🥒 🥓 🥔 🥕 🥖 🥗 🥘 🥙 🥚 🥛 🥜 🥝 🥞 🥟 🥠\
	🥡 🥣 🥤 🥥 🥦 🥧 🥨 🥩 🥪 🥫 🥬 🥭 🥮 🥯 🥰 🥱 🥲 🥳 🥴 🥵 🥶 🥷 🥸 🥹 🥺 🥻\
	🥼 🥽 🥾 🦀 🦁 🦂 🦃 🦄 🦅 🦆 🦇 🦈 🦉 🦊 🦋 🦌 🦍 🦎 🦏 🦐 🦑 🦒 🦓 🦔 🦕 🦖\
	🦗 🦘 🦙 🦚 🦛 🦜 🦝 🦞 🦟 🦠 🦡 🦢 🦣 🦤 🦥 🦦 🦧 🦨 🦩 🦪 🦫 🦬 🦭 🦮 🧀 🧁\
	🧂 🧃 🧄 🧅 🧆 🫠 🫡 🫢 🫣 🫤 🫦 🫧 🫨 ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ⛎)
	emo_generated=true
} 

gen_alea_tab() { # alphanum
	char_tab=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z\
	a b c d e f g h i j k l m n o p q r s t u v w x y z\
	1 2 3 4 5 6 7 8 9)
	alea_generated=true
}

move() {
	mx=''; my='';
	if [[ "$1" -gt 0 ]]; then mx="\e[${1}C"; fi # X
	if [[ "$2" -gt 0 ]]; then my="\e[${2}B"; fi # Y
	printf "\e[0;0H%b%b" "$mx" "$my"
}

# shellcheck disable=SC2317 # see https://www.shellcheck.net/wiki/SC2317
cursor_back() { printf "\e[?25h\n"; } # show cursor
# shellcheck disable=SC2317 # see https://www.shellcheck.net/wiki/SC2317
stop() { move 0 "$lines"; exit 0; } # go last line before exit

timer() {
	read -N 1 -rt "$speed" dummy || true # wait for $speed seconds
	if [ -n "$dummy" ]; then
		case "$dummy" in
			s) speed=".1" ;;
			m) speed=".01" ;;
			d) speed=".001" ;;
			f) speed=".00001" ;;
			a) if $alea; then alea=false
			   else alea=true; emo=false; $alea_generated || gen_alea_tab; fi ;;
			e) if $emo; then emo=false
			   else emo=true; alea=false; $emo_generated || gen_emo_tab; fi ;;
			c) $color && color=false || color=true ;;
			u) $unfix && unfix=false || unfix=true ;;
			p) alea=false; emo=false; char='█' ;;
			i) alea=false; emo=false; move 0 "$lines"; printf "\e[J"; read -rp 'input> ' char ;;
			*) alea=false; emo=false; char="$dummy" ;;
		esac
	fi
}

while [ -n "${1-}" ]; do # parameters
	case "$1" in
		"debug")  set -x ;;
		"slow")   speed=".1" ;;
		"medium") speed=".01" ;;
		"fast")   speed=".00001" ;;
		"ultra")  ultra=true ;;
		"emo")    gen_emo_tab; emo=true; ;;
		"alea")   gen_alea_tab; alea=true; ;;
		"color")  color=true ;;
		"unfix")  unfix=true ;;
		"plain")  char='█' ;;
		*)        char="$1" ;;
	esac
	shift
done

trap cursor_back EXIT INT TERM QUIT
trap stop INT

printf "\e[2J\e[?25l" # clear screen & hide cursor

while true; do
	if $emo; then
		l=2 # emoji use 2 chars space
		char=${emoji[ $(( RANDOM % 517 )) ]}
	else
		[[ "$char" == *$emoji_1f* ]] && l=2 || l=${#char}
		$alea && char=${char_tab[ $(( RANDOM % 61 )) ]}
		if $color
			then selected_color="\e[38;2;$(( RANDOM % 256 ));$(( RANDOM % 256 ));$(( RANDOM % 256 ))m"
			else selected_color=''; printf '\e[0m\e[1m'
		fi
	fi
	if $unfix
		then x=$(( RANDOM % (cols - l) ))
		else x=$(( RANDOM % (cols - l) / l * l ))
	fi
	y=$(( RANDOM % lines ))
	move "$x" "$y"
	printf "%b" "$selected_color$char"
	$ultra || timer
done

exit 0
