#!/usr/local/bin/cbsd
#v12.1.5
CBSDMODULE="bhyve"
MYARG="jname"

jname=
ojname=

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

[ ! -r ${distsharedir}/bhyve_settings.conf ] && err 1 "${N1_COLOR}${CBSD_APP}: no such file: ${N2_COLOR}${distsharedir}/bhyve_settings.conf${N0_COLOR}";
. ${distsharedir}/bhyve_settings.conf

MYCOL="${MYCOL} gid"		# gid located in global SQLite3
ALL_ARGS="${MYCOL}"

MYOPTARG="${MYCOL} mode"
MYDESC="Get info related to bhyve domain"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

Retrieve bhyve VM parameters value. If no arguments are specified,
all parameters will be displayed.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}mode=${N0_COLOR}    - when set to 'quiet' - return value only.
 ${N2_COLOR}<params>${N0_COLOR}  - return value for <params>.

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd bget jname=vm1
 # cbsd bget jname=vm1 mode=quiet vm_cpus vm_ram vm_os_profile

${H3_COLOR}See also${N0_COLOR}:

  cbsd bset --help
  cbsd bconfig --help
  https://github.com/cbsd/cbsd/blob/develop/share/docs/general/tag_n_facts.md

"

cloud_api=0
. ${cbsdinit}

if [ -n "${jname}" ]; then
	# inherit jname env
	ojname="${jname}"
fi

# check for cloud function when CBSDfile exist
Makefile="${CBSD_PWD}/CBSDfile"
if [ -r "${Makefile}" ]; then
	[ -z "${CBSDFILE_RECURSIVE}" ] && ${ECHO} "${N1_COLOR}found CBSDfile: ${N2_COLOR}${Makefile}${N0_COLOR}" 1>&2
	. ${Makefile}
	all_bhyve_list=$( ${GREP_CMD} -E '^bhyve_[a-zA-Z0-9_@%:][-a-zA-Z0-9_@%:]*\(\)$' ${Makefile} | ${XARGS_CMD} | ${TR_CMD} -d "()" | ${SED_CMD} s#bhyve_##g )

	if [ -n "${CLOUD_URL}" -a -n "${CLOUD_KEY}" ]; then
		cbsd_api=1
	else
		cbsd_api=0
	fi

	if [ -n "${jname}" ]; then
		found=0
		for i in ${all_bhyve_list}; do
			if [ "${i}" = "${jname}" ]; then
				found=1
				break
			fi
		done
		[ ${found} -eq 0 ] && err 1 "${N1_COLOR}${CBSD_APP}: no such bhyve: ${N2_COLOR}${jname}${N0_COLOR}"
	fi
else
	jname="${all_bhyve_list}"
	cbsd_api=0
fi

# only ip4_addr value supported
if [ ${cbsd_api} -eq 1 ]; then
	CURL_CMD=$( which curl )
	[ -z "${CURL_CMD}" ] && err 1 "${N1_COLOR}cloud up requires curl, please install: ${N2_COLOR}pkg install -y curl${N0_COLOR}"
	[ -z "${CBSDFILE_RECURSIVE}" ] && ${ECHO} "${N1_COLOR}main cloud api: ${N2_COLOR}${CLOUD_URL}${N0_COLOR}" 1>&2
	_cid=$( ${miscdir}/cbsd_md5 "${CLOUD_KEY}" )
	for _jname in ${all_bhyve_list}; do
		_ssh=$( ${CURL_CMD} --no-progress-meter -H "cid:${_cid}" ${CLOUD_URL}/api/v1/status/${_jname} 2>&1 )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "${N1_COLOR}${CBSD_APP} error: curl status error: ${N2_COLOR}${_ssh}${N0_COLOR}"
			${ECHO} "${CURL_CMD} --no-progress-meter -H \"cid:XXXXX\" ${CLOUD_URL}/api/v1/status/${_jname}"
			continue
		fi
		_ssh_pref=$( substr --pos=0 --len=3 --str="${_ssh}" )
		if [ "${_ssh_pref}" != "ssh" ]; then
			${ECHO} "${N1_COLOR}${CBSD_APP} error: curl error: ${N2_COLOR}${_ssh}${N0_COLOR}"
			${ECHO} "${CURL_CMD} --no-progress-meter -H \"cid:XXXXX\" ${CLOUD_URL}/api/v1/status/${_jname}"
			continue
		fi
		_ssh_len=$( strlen "${_ssh}" )
		_ssh_post=$( substr --pos=5 --len=${_ssh_len} --str="${_ssh}" )
		_ip=$( echo ${_ssh_post} | ${AWK_CMD} '{printf $1}' | ${TR_CMD} "@" " " | ${AWK_CMD} '{printf $2}' )
		[ -z "${_ip}" ] && exit 1
		echo "${_ip}"
	done
	exit 0
fi

[ -n "${ojname}" ] && jname="${ojname}"
[ -z "${jname}" ] && err 1 "Give me jname"

# push orig MYCOL
OMYCOL="${MYCOL}"

. ${subrdir}/rcconf.subr

if [ $? -eq 1 ]; then
	#
	# try_remote, todo
	sqlfile_sysdir="${tmpdir}/${1}"
	err 1 "${N1_COLOR}No such bhyve: ${N2_COLOR}${jname}${N0_COLOR}"
else
	sqlfile_sysdir="${jailsysdir}"
fi
[ "${emulator}" != "bhyve" ] && err 1 "${N1_COLOR}not bhyve engine, emulator: ${N2_COLOR}${emulator}${N0_COLOR}"
if [ "${mode}" = "quiet" ]; then
	QUIET=1
else
	QUIET=0
fi

ARGS=				# known args ( MYCOL)
UNKNOWN_ARGS=			# unknown args ( external/custom ? )

# exclude jname= and mode= params from args str
for i in $*; do
	prefix3=$( substr --pos=0 --len=3 --str=${i} )
	prefix5=$( substr --pos=0 --len=5 --str=${i} )
	prefix6=$( substr --pos=0 --len=6 --str=${i} )
	[ "${prefix5}" = "mode=" ] && continue
	[ "${prefix6}" = "jname=" ] && continue

	is_known_args=0

	for _jarg in ${OMYCOL}; do
		if [ "${_jarg}" = "${i}" ]; then
			ARGS="${ARGS} ${i}"
			is_known_args=1
			break
		fi
	done

	if [ ${is_known_args} -eq 0 ]; then
		UNKNOWN_ARGS="${UNKNOWN_ARGS} ${i}"
	fi
done

# empty known params and found unknown (+ third option in mind: custom_facts): so return all
[ -z "${ARGS}" -a -z "${UNKNOWN_ARGS}" ] && ARGS="${ALL_ARGS}"

for OID in ${ARGS}; do
	case "${OID}" in
		vnc)
			_vnc_port=$( cbsdsqlro ${sqlfile_sysdir}/${jname}/local.sqlite "SELECT vnc_port FROM settings LIMIT 1" )
			_bhyve_vnc_tcp_bind=$( cbsdsqlro ${sqlfile_sysdir}/${jname}/local.sqlite "SELECT bhyve_vnc_tcp_bind FROM settings LIMIT 1" )
			val="${_bhyve_vnc_tcp_bind}:${_vnc_port}"
			;;
		gid)
			# gid is global env ID, located in global/index database
			val=$( cbsdsqlro ${dbdir}/local.sqlite "SELECT gid FROM jails WHERE jname=\"${jname}\"" )
			;;
		*)
			val=$( cbsdsqlro ${sqlfile_sysdir}/${jname}/local.sqlite "SELECT ${OID} FROM settings LIMIT 1" )
			;;
	esac

	[ "${val}" = "(null)" -o -z "${val}" ] && val=0

	if [ ${QUIET} -eq 1 ]; then
		echo "${val}"
	else
		echo "${OID}: ${val}"
	fi
done

# search for custom column output helper first
for OID in ${UNKNOWN_ARGS}; do
	[ ! -x ${jailsysdir}/${jname}/facts.d/${OID} ] && continue
	. ${subrdir}/jcreate.subr		# for export_jail_data_for_external_hook
	geniplist ${ip4_addr}                   # for ipvX_first_public-like vars
	export_jail_data_for_external_hook
	val=$( ${jailsysdir}/${jname}/facts.d/${OID} | ${HEAD_CMD} -1 | ${AWK_CMD} '{printf $1}' )
	if [ ${QUIET} -eq 1 ]; then
		echo "${val}"
	else
		echo "${OID}: ${val}"
	fi
done

exit 0
