#!/bin/zsh

# on peut utiliser certains caractres pour afficher des flches dans les menus :
# \x10, \x15 : flches droites
# \x11, \x14 : flches gauches
# \x12, \x1A, \x1D : flches hautes
# \x13, \x1E : flches basses
# \x16 : flche haut-gauche
# \x17 : flche haut-droite
# \x18 : flche bas-gauche
# \x19 : flche bas-droite
# \x1C : return
# \x1F : bloc carr

# read the smartcard code
read_smartcard() {
	read < /dev/smartcard
	echo $REPLY
}

# verifies if the current smartcard matches a given profile
check_profile() {
	read < /dev/smartcard
	grep -q "^$REPLY:$1\$" /etc/smartcards
}

# ask for a valid card for a given profile or any key to exit
ask_for_card() {
	while ! check_profile $1; do
		echo -n '\e[Lb\e[Lc\e[L+\e[2J' > /dev/lcd
		echo -n '\e[Lx0y0;Use a valid card' > /dev/lcd
		echo -n '\e[Lx0y1;or press any key' > /dev/lcd
		read < /dev/keypad
		case "$REPLY" in
		"Card"*)	# a card event
			;;
		*)	# any other key
			return 1 # return invalid card
			;;
		esac
	done
	return 0
}

# first argument is the profile required to access this menu
display_menu() {
	menu=1
	# check if the card is still valid for this menu
	if ! ask_for_card $1; then
		echo -n '\e[Lb\e[Lc\e[L-\e[L*\e[2J' > /dev/lcd
		return 0
	fi
	echo -n '\e[Lb\e[Lc\e[2J\e[L*' > /dev/lcd
	if check_profile $profils[$menu]; then
		echo -n '\x10' > /dev/lcd
	else
		echo -n '\x11' > /dev/lcd
	fi
	echo -n $noms[$menu]'\e[Lx0y1; '$noms[$[$menu]+1] > /dev/lcd
	while read < /dev/keypad; do
		case "$REPLY" in
		"Up"|"Left")
			echo -n '\e[L-\e[L*' > /dev/lcd
			if [ $menu -gt 1 ]; then menu=$[$menu-1]; fi
			;;
		"Down"|"Right")
			echo -n '\e[L-\e[L*' > /dev/lcd
			if [ $menu -lt $#noms ]; then menu=$[$menu+1]; fi
			;;
		"Ret")
			if check_profile $profils[$menu]; then
				echo -n '\e[LC\e[LB\e[2J\e[L+\x10'$noms[$menu]"\r" > /dev/lcd
				eval $fonctions[$menu] "$param[$menu]"
				ret=$?
				echo -n '\e[Lb\e[Lc\e[2J\e[L-\e[L*\x1C'$noms[$menu] > /dev/lcd
				if [ $retour[$menu] -gt 0 ]; then
					return $ret
				fi
			fi
			;;
		"Esc")
			echo -n '\e[Lb\e[Lc\e[L-\e[L*\e[2J' > /dev/lcd
			return 0		# Esc=retour au menu parent
			;;
		*)
			# check if the card is still valid for this menu
			ask_for_card $1
			;;
		esac;
		# check if the card is still valid for this menu, in case we exited from another one
		if ! check_profile $1; then
			echo -n '\e[Lb\e[Lc\e[L-\e[L*\e[2J' > /dev/lcd
			return 0
		fi
		echo -n '\e[Lb\e[Lc\e[2J\e[L*' > /dev/lcd
		if check_profile $profils[$menu]; then
			echo -n '\x10' > /dev/lcd
		else
			echo -n '\x11' > /dev/lcd
		fi
		echo -n $noms[$menu]'\e[Lx0y1; '$noms[$[$menu]+1] > /dev/lcd
	done
	echo 'ERROR ! should never get here !!'
	return 1
}


# network, bitmask, ip
mask_from_int() {
	if [ $1 -eq 0 ]; then echo 000.000.000.000
	elif [ $1 -ge 32 ]; then echo 255.255.255.255
	elif [ $1 -le 8 ]; then echo $[256-(1<<(7-(($1-1) % 8)))].000.000.000
	elif [ $1 -le 16 ]; then echo 255.$[256-(1<<(7-(($1-1) % 8)))].000.000
	elif [ $1 -le 24 ]; then echo 255.255.$[256-(1<<(7-(($1-1) % 8)))].000
	else echo 255.255.255.$[256-(1<<(7-(($1-1) % 8)))]
	fi
}

# retourne 0 si pas de modif, 1 si modif
get_mask() {
	varname=$1
	title=$2
	eval mask_orig=$mask
	echo -n "\e[LC\e[LB\e[2J\e[L+$title\e[Lx0y1;"`mask_from_int $mask` > /dev/lcd
	while read < /dev/keypad; do
		case "$REPLY" in
 		"Up")
			if [ $mask -lt 32 ]; then mask=$[$mask + 1]; fi
			;;
		"Down")
			if [ $mask -gt 0 ]; then mask=$[$mask - 1]; fi
			;;
		"Right")
			if [ $mask -lt 32 ]; then mask=$[($mask + 8) & -8]; fi
			;;
		"Left")
			if [ $mask -gt 0 ]; then mask=$[($mask - 1) & -8]; fi
			;;
		"Ret")
			echo -n '\e[Lx0y1;\e[L-\e[L*\e[LC\e[Lb'`mask_from_int $mask` > /dev/lcd
			if [ $mask -ne $mask_orig ]; then
				echo "export $varname=$mask"
				export $varname=$mask
				return 1
			else
				return 0
			fi
			;;
		"Esc")
			mask=$mask_orig
			echo -n '\e[Lx0y1;\e[L-\e[L*\e[LC\e[Lb'`mask_from_int $mask` > /dev/lcd
			return 0
			;;
		esac;
		echo -n '\e[Lx0y1;'`mask_from_int $mask` > /dev/lcd
	done
	echo 'ERROR ! should never get here !!'
	return 0
}

# retourne 0 si pas de modif, 1 si modif
# ex d'appel :
# export CFG_IF_eth0_MASK=24
# show_mask eth0

show_mask() {
	modif=0
	varname=$1
	title=$2
	eval mask=$"$varname"
	if [ -z "$mask" ]; then mask=24; fi
	echo -n "\e[LC\e[Lb\e[2J\e[L+\x10$title\e[Lx0y1;"`mask_from_int $mask` > /dev/lcd
	while read < /dev/keypad; do
		case "$REPLY" in
		"Up"|"Left")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 1		# champ precedent
			;;
		"Down"|"Right")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 2		# champ suivant
			;;
		"Ret")
			echo -n '\e[L-\e[L*' > /dev/lcd
			get_mask $varname $title
			modif=$[$modif | $?]
			return 0		# Ret=edition du champ puis retour
			;;
		"Esc")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 3		# Esc=validation de l'ecran
			;;
		esac;
		echo -n '\e[Lx0y1;\e[L+'`mask_from_int $mask` > /dev/lcd
	done
	echo 'ERROR ! should not get here !!'
	return 0
}

format_ip() {
	printf "%03d.%03d.%03d.%03d" $1 $2 $3 $4
}

# retourne 0 si pas de modif, 1 si modif
get_address() {
	varname=$1
	title=$2
	set -A octets_orig $octets
	cur_octet=1
	echo -n "\e[LC\e[LB\e[2J\e[L+$title\e[Lx0y1;"`format_ip $octets`"\e[Lx3y1;" > /dev/lcd
	while read < /dev/keypad; do
		case "$REPLY" in
		"Up")
			if [ $octets[$cur_octet] -lt 255 ]; then
				octets[$cur_octet]=$[$octets[$cur_octet]+1];
			else
				octets[$cur_octet]=0;
			fi
			;;
		"Down")
			if [ $octets[$cur_octet] -gt 0 ]; then
				octets[$cur_octet]=$[$octets[$cur_octet]-1];
			else
				octets[$cur_octet]=255;
			fi
			;;
		"Right")
			if [ $cur_octet -lt 4 ]; then let cur_octet++; fi
			;;
		"Left")
			if [ $cur_octet -gt 1 ]; then let cur_octet--; fi
			;;
		"Ret")
			echo -n '\e[Lx0y1;\e[L-\e[L*\e[LC\e[Lb'`format_ip $octets` > /dev/lcd
			if [ "${(pj:.:)octets}" != "${(pj:.:)octets_orig}" ]; then
				echo "export $varname=${(pj:.:)octets}"
				export $varname=${(pj:.:)octets}
				return 1
			else
				return 0
			fi
			;;
		"Esc")
			set -A octets $octets_orig
			echo -n '\e[Lx0y1;\e[L-\e[L*\e[LC\e[Lb'`format_ip $octets` > /dev/lcd
			return 0
			;;
		esac;
		echo -n '\e[Lx0y1;'`format_ip $octets`'\e[Lx'$[$cur_octet*4-1]'y1;' > /dev/lcd
	done
	echo 'ERROR ! should never get here !!'
	return 0
}

# retourne 0 si pas de modif, 1 si modif
#
# export CFG_IF_eth0_ADDR=1.23.456.789
# show_address eth0

show_address() {
	modif=0
	varname=$1
	title=$2
	eval adresse=$"$varname"
	if [ -z "$adresse" ]; then adresse="0.0.0.0"; fi
	octet1=${adresse%%.*}
	octet2=${adresse##$octet1.};octet2=${octet2%%.*}
	octet3=${adresse##$octet1.$octet2.};octet3=${octet3%%.*}
	octet4=${adresse##$octet1.$octet2.$octet3.}

	set -A octets $octet1 $octet2 $octet3 $octet4

	echo -n "\e[LC\e[Lb\e[2J\e[L+\x10$title\e[Lx0y1;"`format_ip $octets` > /dev/lcd
	while read < /dev/keypad; do
		case "$REPLY" in
		"Up"|"Left")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 1		# champ precedent
			;;
		"Down"|"Right")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 2		# champ suivant
			;;
		"Ret")
			echo -n '\e[L-\e[L*' > /dev/lcd
			get_address $varname $title
			modif=$[$modif | $?]
			return 0		# Ret=edition du champ puis retour
			;;
		"Esc")
			echo -n '\e[L-\e[L*' > /dev/lcd
			return 3		# Esc=validation de l'ecran
			;;
		esac;
		echo -n '\e[Lx0y1;\e[L+'`format_ip $octets` > /dev/lcd
	done
	echo 'ERROR ! should never get here !!'
	return 0
}

display_items() {
	item=1
	while :; do
		# check if the card is still valid for this menu
		if ! ask_for_card $1; then
			echo -n '\e[Lb\e[Lc\e[L-\e[L*\e[2J' > /dev/lcd
			return 0
		fi
		eval $fonctions[$item] \"$param[$item]\" \"$noms[$item]\"
		case $? in
		1)	# up
			if [ $item -gt 1 ]; then item=$[$item-1]; fi
			;;
		2)	# down
			if [ $item -lt $#noms ]; then item=$[$item+1]; fi
			;;
		3)	# escape valide l'cran
			#for i in $#noms; do
			#	echo "$variables[$i]=$valeurs[$i] # ($noms[$i])"
			#done
			return 0
			;;
		# 0 = return : on ne sort pas
		esac
	done
}

