#!/usr/local/bin/cbsd
#v12.1.9

. ${subrdir}/nc.subr
. ${strings}
. ${tools}

[ ! -f "${distsharedir}/jail-arg" ] && err 1 "No such jail-arg skel"
. ${distsharedir}/jail-arg
CBSDMODULE="bhyve"
MYDESC="Dialog-based text user interface for bhyve VM configuration"
MYARG="jname"
MYOPTARG="${JARG} outfile"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

Text user interface for bhyve VM configuration. This script invoked by 'cbsd bconfig'.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}jname=${N0_COLOR}     - work with <VM>;

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd bsetup-tui jname=vm1

${H3_COLOR}See also${N0_COLOR}:

  cbsd bconfig --help
  cbsd bget --help
  cbsd bset --help

"

. ${cbsdinit}
. ${subrdir}/settings-tui.subr
. ${subrdir}/settings-tui-virtual.subr
. ${subrdir}/settings-tui-bhyve.subr
. ${dialog}

commit()
{
	local _oldjname _newjname TMPVAL

	_oldjname="${jname}"

	for i in ${JARG}; do
		eval VAL=\$$i
		eval OVAL=\$OLDVAL_${i}

		if [ "${i}" = "jname" ]; then
			_oldjname="${OVAL}"
			_newjname="${VAL}"
			continue
		fi

		if [ "${i}" = "vm_ram" ]; then
			# In SQLite3 we store vm_ram in bytes, convert it
			# test for human
			if is_number ${VAL}; then
				if conv2bytes ${VAL}; then
					VAL="${convval}"
				fi
			else
				# Assume than user input in MB, so convert to bytes
				VAL=$(( convval * 1024 * 1024 ))
			fi
		fi

		[ "${VAL}" = "${OVAL}" ] && continue

		if [ "${i}" = "vm_ram" ]; then
			# In SQLite3 we store vm_ram in bytes, convert it
			VAL=$(( VAL / 1024 / 1024 ))
		fi

		# convert spaces to '%' for bset ( see todo in init func from nc.subr for val="one two" )
		TMPVAL=$( echo "${VAL}" | ${TR_CMD} ' ' '%' )

		bset mode=quiet jname=${_oldjname} ${i}="${TMPVAL}"
	done

	[ "${_oldjname}" != "${_newjname}" -a -n "${_newjname}" ] && cbsd brename old=${_oldjname} new=${_newjname}

	exit 0
}


store_defaults()
{
	local i VAL

	eval $( for i in "jname" ${JARG}; do
		[ "${i}" = "repo" ] && repo=1 && continue
		eval VAL=\$$i
		echo "OLDVAL_${i}=\"${VAL}\""
	done )
}


dialog_menu_main()
{
	title=" Config for ${jname} VM "
	hline=
	local defaultitem=

	local menu_list="
		'EXIT'  'EXIT'  'Exit jconstruct-tui'
	" # END-QUOTE

	local i _mytest skip
	local _checkbox="astart protected hidden bhyve_generate_acpi bhyve_wire_memory bhyve_rts_keeps_utc bhyve_force_msi_irq bhyve_x2apic_mode bhyve_mptable_gen bhyve_ignore_msr_acc xhci tablet fbuf jailed chrooted double_acpi virtio_rnd"

	# don't show it in main menu:
	local _in_sub_menu="bhyve_generate_acpi bhyve_wire_memory bhyve_rts_keeps_utc bhyve_force_msi_irq bhyve_x2apic_mode bhyve_mptable_gen bhyve_ignore_msr_acc cd_vnc_wait bhyve_vnc_resolution bhyve_vnc_tcp_bind \
	vnc_password bhyve_vnc_vgaconf on_crash on_poweroff on_reboot double_acpi virtio_rnd bhyverun_wrapper bhyvestop_wrapper boot_delay bhyve_cmd efi_firmware bhyve_vnc_kbdlayout tpm"

	item_let="A"
	item_num=0

	 f_dialog_default_fetch defaultitem

	# checkbox mark
	for i in ${_checkbox}; do
		eval _mytest=\$$i
		if [ "${_mytest}" = "1" ]; then
			export ${i}_mark="X"
		else
			export ${i}_mark=" "
		fi
	done

	for i in ${JARG}; do
		skip=0

		# skip for _in_sub_menu list item:
		for y in ${_in_sub_menu}; do
				[ "${i}" = "${y}" ] && skip=1
		done

		[ ${skip} -eq 1 ] && continue

		for x in ${_checkbox}; do

			[ ${skip} -eq 1 ] && break

			if [ "${x}" = "${i}" ]; then

				if [ "${x}" = "tablet" ]; then
					# skip tablet when xhci off
					[ "${xhci}" = "0" ] && skip=1 && break
				fi


				eval _mytest=\$${x}_mark
				[ -z "${_mytest}" ] && _mytest=" "
				inc_menu_index item_let
				menu_list="${menu_list} '${item_let} ${x}'      '[${_mytest}]'  '${_mydesc}'"
				skip=1
			fi

		done

		[ ${skip} -eq 1 ] && continue

		inc_menu_index item_let

		eval VAL=\$$i

		if [ "${i}" = "vm_ram" ]; then
			# test for human
			if ! is_number ${VAL}; then
				if conv2human "${VAL}"; then
					VAL=${convval}
					vm_ram="${VAL}"
				fi
			fi
		fi

		if [ -z "${VAL}" ]; then
			menu_list="${menu_list} '${item_let} ${i}'	' '	'Descr?'"
		else
			menu_list="${menu_list} '${item_let} ${i}'	'${VAL}'	'Descr?'"
		fi
	done

	menu_list="${menu_list} '-'	'-' ''"
	menu_list="${menu_list} 'bhyve_controller'	'Controller config >>'	'cbsd bhyve-controller-tui'"
	menu_list="${menu_list} 'bhyvedsk'		'Storage config >>'	'cbsd bhyve-dsk-tui'"
	menu_list="${menu_list} 'bhyvenic'		'Network config >>'	'cbsd bhyve-nic-tui'"
	menu_list="${menu_list} 'LPC'			'LPC devices >>'	'cbsd blpc'"

	# FreeBSD-13+ only
	if [ ${freebsdhostversion} -gt 1300033 ]; then
		#inc_menu_index item_num
		menu_list="${menu_list} 'bhyve_audio_options'	'Audio options >>'	'audio opt: ${soundhw}'"
	fi

	menu_list="${menu_list} 'bhyve_options'			'Bhyve options >>'	'customize bhyve options: acpi:${bhyve_generate_acpi}, wire:${bhyve_wire_memory} rts_utc:${bhyve_rts_keeps_utc} msi:${bhyve_force_msi_irq} x2apic:${bhyve_x2apic_mode} mptable:${bhyve_mptable_gen} ign_acc:${bhyve_ignore_msr_acc}'"

	if [ "${vm_efi}" != "none" ]; then
		if [ "${fbuf}" = "1" ]; then
			menu_list="${menu_list} 'bhyve_vnc_options'	'VNC options >>'	'customize VNC options: cd_wait:${cd_vnc_wait} resolution:${bhyve_vnc_resolution} bind:${bhyve_vnc_tcp_bind}'"
			inc_menu_index item_num
		fi
	fi

	menu_list="${menu_list} 'bhyve_flags'		'Additional bhyve_flags'	'customize additional bhyve_flags. Current: ${bhyve_flags}'"

	menu_list="${menu_list} 'order'			'Boot order >>'			'cbsd border-tui'"
	menu_list="${menu_list} 'cd_boot_firmware'	'Select CD boot firmware'	'change CD boot firmware.'"
	menu_list="${menu_list} 'hdd_boot_firmware'	'Select HDD boot firmware'	'change HDD boot firmware.'"
	menu_list="${menu_list} 'exit_behavior'		'Exit behavior settings'	'exit behavior settings: poweroff:${on_poweroff},reboot:${on_reboot},crash:${on_crash}'"

	menu_list="${menu_list} '-'	'-' ''"
	menu_list="${menu_list} 'COMMIT'	'Save changes and quit'	'Save!'"

	cbsd_menubox
	retval=$?

	f_dialog_data_sanitize menu_choice
	f_dialog_menutag_store "$menu_choice"
	f_dialog_default_store "$menu_choice"

	return $retval
}

### MAIN
readconf bhyve-default-default.conf


. ${subrdir}/rcconf.subr
[ $? -eq 1 ] && err 1 "${N1_COLOR}no such jail: ${N2_COLOR}${jname}${N0_COLOR}"
[ "${emulator}" != "bhyve" ] && err 1 "${N1_COLOR}Only for bhyve type VMs${N0_COLOR}"

shift #skip for jname

JARG="$@"

f_dialog_title "$msg_system_console_configuration"
f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
f_mustberoot_init

store_defaults

# fill promt variable used in dialog_menu_main about active jail status
# otherwise - append the argument that we can change also and jname.
if [ ${jid} -ne 0 ]; then
	prompt="VM is ONLINE!\nSome parameters require a bstop/bstart cycle!"
else
	JARG="jname ${JARG}"
fi

while [ 1 ]; do
	dialog_menu_main || f_die

	index=${mtag%% *}
	mychoice=${mtag##* }

	case "${mychoice}" in
		"-")
			continue
			;;
		"bhyve_options")
			get_construct_bhyve_options
			;;
		"bhyve_vnc_options")
			get_construct_bhyve_vnc_options
			;;
		"bhyvenic")
			bhyve-nic-tui jname=${jname}
			;;
		"LPC")
			blpc-tui jname=${jname}
			;;
		"bhyvedsk")
			bhyve-dsk-tui jname=${jname}
			;;
		"bhyve_controller")
			bhyve-controller-tui jname=${jname}
			;;
		b_order|order)
			border-tui jname="${jname}"
			b_order=$( cbsdsqlro local "SELECT b_order FROM jails WHERE jname=\"${jname}\"" 2>/dev/null )
			;;
		"EXIT")
			f_die
			;;
		"COMMIT")
			commit
			;;
		astart|protected|hidden|bhyve_generate_acpi|bhyve_wire_memory|bhyve_rts_keeps_utc|bhyve_force_msi_irq|bhyve_x2apic_mode|bhyve_mptable_gen|bhyve_ignore_msr_acc|xhci|tablet|fbuf|jailed|chrooted|double_acpi|virtio_rnd)
			invert_checkbox ${mychoice}
			continue
			;;
		interface)
			get_construct_interface -d 1 -s "tap bridge vboxnet"
			;;
		bhyve_audio_options)
			soundhw_play=$( cbsdsqlro ${jailsysdir}/${jname}/local.sqlite SELECT soundhw_play FROM bhyve_soundhw 2>/dev/null )
			soundhw_rec=$( cbsdsqlro ${jailsysdir}/${jname}/local.sqlite SELECT soundhw_rec FROM bhyve_soundhw 2>/dev/null )
			get_construct_bhyve_audio_options -u
			;;
		*)
			get_construct_${mychoice}
			;;
	esac
done

exit 0
