#!/usr/local/bin/cbsd
#v10.1.2
MYARG=
MYOPTARG="conf controlmaster out repo"
MYDESC="Generate chosen package list from repository"
CBSDMODULE="jail"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

TUI-based dialog for select package list from ports category. The result can be 
saved to a file. Used by TUI dialog for data exchange.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}conf${N0_COLOR}          - use this pkg.conf;
 ${N2_COLOR}controlmaster${N0_COLOR} - use this pkg.conf;
 ${N2_COLOR}out${N0_COLOR}           - path_to_file with result, instead of random;
 ${N2_COLOR}repo${N0_COLOR}          - use this repository;

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd pkgbrowser controlmaster=/tmp/test
 # cat /tmp/test

"

. ${subrdir}/nc.subr
. ${cbsdinit}
. ${dialog}

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

readconf pkgbrowser.conf

input_manual()
{
	local _input
	local msg="Enter space-separated name or origin for packages.\n E.g: 'ca_root_nss www/nginx www/apache24 lang/php71 misc/mc ftp/wget shells/bash'"

	f_dialog_title " pkglist "

	f_dialog_input _input "${msg}" "${ver}" \
		"${_message}" || return $?

	pkglist="${_input}"
}

populate_menu_by_category()
{
	local width

	cat_id="${1}"
	cat_name="${2}"

	[ -z "${cat_id}" -o -z "${cat_name}" ] && return 1

	local _tmpdir="${tmpdir}/pkg"
	[ ! -d "${_tmpdir}" ] && ${MKDIR_CMD} "${_tmpdir}"

	[ -r "${_tmpdir}/${cat_name}.mnu" -a ${UPDATED} -eq 0 ] && return 0

	echo 'menu_list="' > ${_tmpdir}/${cat_name}.mnu
	echo "'EXIT'	'EXIT'	'Exit this menu'" >> ${_tmpdir}/${cat_name}.mnu

	${TRUNCATE_CMD} -s0 ${_tmpdir}/${cat_name}.idx
	${RM_CMD} -f ${_tmpdir}/${cat_name}.idx.gz

	local msg="Re-index and dialogizing for ${cat_name}..."
	width=50

	$DIALOG \
		--title " repo updated "   \
		--backtitle " pkgbrowser " \
		--infobox "${msg}" 4 ${width}

	local sqldelimer="|"
	local OIFS="${IFS}"
	local IFS="|"

	local i=0

	local prefix=X
	local cur_prefix=Y

	cbsdsqlro /var/db/pkg/${repofile} "SELECT name,origin,comment,flatsize FROM packages WHERE id IN ( SELECT package_id FROM pkg_categories WHERE category_id=\"${cat_id}\" ) AND id IN ( SELECT packages.id FROM packages LEFT JOIN deps ON packages.origin = deps.origin WHERE deps.origin IS NULL ) ORDER BY name" | while read name origin comment flatsize; do
		IFS="${OIFS}"
		prefix=$( substr --pos=0 --len=1 --str=${name} )

		if [ "${prefix}" != "${cur_prefix}" ]; then
			cur_prefix="${prefix}"
		else
			prefix=""
		fi

		comment=$( echo "${comment}"  | ${TR_CMD} -d "\"()'\`" )
		markname=$( echo "${name}" | ${TR_CMD} -d "\"()'\`-.+" )

		if ! is_number ${flatsize}; then
			if conv2human "${flatsize}"; then
				flatsize=${convval}
			fi
		else
			flatsize="0"
		fi

		echo "export pkgmark_${markname}_origin='${origin}'" >> ${_tmpdir}/${cat_name}.idx
		echo "'${prefix} ${name}'	'[\$pkgmark_${markname}] ${origin}'	'${comment}. Size: ${flatsize}'" >> ${_tmpdir}/${cat_name}.mnu
		IFS="|"
	done

	IFS="${OIFS}"

	${GZIP_CMD} -9 ${_tmpdir}/${cat_name}.idx
	echo '"' >> ${_tmpdir}/${cat_name}.mnu
}

browse_category()
{
	local title=" ${repofile} "
	local btitle="Select packages"
	local prompt=""
	local defaultitem=
	local hline="Hit ENTER for SELECT"
	local prompt=" Choose category and select packages.\nSelected: ${pkgnum} "
	local kversion

	local f_dialog_title=" FreeBSD repository "
	f_dialog_default_fetch defaultitem

	local menu_list=" \
		'EXIT'		'<<'			'Exit this menu' \
		'MANUAL'	'Input manually'	'Enter origin or package name by hand in inputbox' \
		'-'	'-'	'' \
	" # END-QUOTE

	local num=0

	local sqldelimer="|"
	local IFS="|"

	eval $( cbsdsqlro /var/db/pkg/${repofile} 'SELECT id,name FROM categories ORDER BY name' | while read id name; do
			echo "local id_${num}=\"${id}\""
			echo "local name_${num}=\"${name}\""
			num=$(( num + 1 ))
	done )

	unset IFS
	unset sqldelimer


	for num in $( ${SEQ_CMD} 0 200 ); do
		eval id="\$id_${num}"
		[ -z "${id}" ] && break
		eval name="\$name_${num}"
		[ -z "${name}" ] && break;
		skip=0

		# strict list by pkgbrowser.conf
		for i in ${IGNORE_CATEGORY}; do
			[ "${name}" = "${i}" ] && skip=1 && break
		done

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

		populate_menu_by_category "${id}" "${name}"
		menu_list="${menu_list} '${name}'	''	''"
	done

	IFS=" "

	cbsd_menubox
	retval=$?

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

	return $retval
}


### MAIN ###
[ -z "${out}" ] && out="${tmpdir}/pkgbrowser.$$"
PKGCONF=""
PKGOPT=""
PKG_MODIFIED="${tmpdir}/pkg_updated.txt"
UPDATED="0"

# controlmaster for submenu
CONTROLMASTER=$( ${MKTEMP_CMD} )
${TOUCH_CMD} ${CONTROLMASTER}

trap "${RM_CMD} -f ${CONTROLMASTER}" HUP INT ABRT BUS TERM EXIT

f_dialog_info "Executing pkg update..."

#printf "${N1_COLOR}Update local copy of repository catalogues...${N0_COLOR}"
#tst=$( ${ENV_CMD} IGNORE_OSVERSION=yes SIGNATURE_TYPE=none ${TIMEOUT_CMD} 60 ${PKG_CMD} update -f 2>&1 )
#[ $? -ne 0 ] && err 1 "${N1_COLOR}pkg update failed: ${N0_COLOR}${tst}"

allrepos=$( ${FIND_CMD} /var/db/pkg/ -mindepth 1 -maxdepth 1 -name repo-\*.sqlite -type f -exec ${miscdir}/cbsd_md5 {} \; | ${XARGS_CMD} )
tst=$( ${miscdir}/cbsd_md5 "${allrepos}" )

if [ -f "${PKG_MODIFIED}" ]; then
	oldmd5=$( ${CAT_CMD} ${PKG_MODIFIED} )
	if [ "${oldmd5}" != "${tst}" ]; then
		UPDATED="1"
		echo "${tst}" > ${PKG_MODIFIED}
	fi
else
	echo "${tst}" > ${PKG_MODIFIED}
	UPDATED="1"
fi

REPOFILE="repo"

pkgnum=0

while :; do

	# calculate num of selected pkg. pkglist variable from input_manual method is preferred.
	if [ -z "${pkglist}" ]; then
		pkgnum=$( ${GREP_CMD} -E -v '(pkgmark_)*(_origin=)' ${CONTROLMASTER} | ${WC_CMD} -l | ${AWK_CMD} '{printf $1}' )
	else
		pkgnum=$( echo ${pkglist} | ${WC_CMD} -w | ${AWK_CMD} '{printf $1}' )
	fi

	browse_category || break
	UPDATED=0

	[ -z "${mtag}" ] && exit $SUCCESS

	case "$mtag" in
		"EXIT")
			. ${CONTROLMASTER}
			if [ -z "${controlmaster}" ]; then
				controlmaster="/dev/stdout"
			else
				[ ! -f ${controlmaster} ] && ${TRUNCATE_CMD} -s0 ${controlmaster}
			fi

			# store selected pkg. pkglist variable from input_manual method is preferred
			if [ -z "${pkglist}" ]; then
				for i in $( printenv | ${GREP_CMD} -E '(pkgmark_)*(_origin=)' | ${CUT_CMD} -d "=" -f 2 ); do
					echo "${i}" >> ${controlmaster}
				done
			else
				echo "${pkglist}" >> ${controlmaster}
			fi

			if [ -f "${controlmaster}" ]; then
				${MV_CMD} ${controlmaster} ${controlmaster}.$$
				${SORT_CMD} -u ${controlmaster}.$$ > ${controlmaster}
				${RM_CMD} -f ${controlmaster}.$$
			fi
			f_die
			;;
		"MANUAL")
			input_manual
			;;
		"-")
			continue
			;;
		*)
			pkgbrowsecat name="${mtag}" controlmaster="${CONTROLMASTER}"
			continue
			;;
	esac

	if [ "$command" ]; then
		$BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
	fi
done

return $SUCCESS
