#!/bin/sh
#
# Spk-ls - List SliTaz packages and files. Read the README before adding or
# modifying any code in spk!
#
# Copyright (C) SliTaz GNU/Linux - BSD License
# Author: See AUTHORS files
#
. /usr/lib/slitaz/libspk.sh

#
# Functions
#

# Help and usage
usage() {
	name=$(basename $0)
	cat << EOT

$(boldify $(gettext "Usage:")) $name [packages|--options]

$(gettext "List packages or installed files by packages")

$(boldify $(gettext "Options:"))
  --count      $(gettext "Display the number of installed packages")
  --mirror     $(gettext "List all the packages on mirror")
  --extra      $(gettext "List packages on extra mirrors ")
  --blocked    $(gettext "List all blocked packages")
  --short      $(gettext "Short packages list format")
  --modifiers  $(gettext "List package modifiers")
  --raw        $(gettext "Plain TSV, scriptable, stable format")
  --trame      $(gettext "JSON object on stdout, aligned with trame conventions")
  --root=      $(gettext "Set the root file system path")
  --color=NB   $(gettext "Set package name color in list")
  --debug      $(gettext "Display some useful debug information")

$(boldify $(gettext "Examples:"))
  $name package1 package2 packageN
  $name --short --color=33

EOT
	exit 0
}

#
# Output mode + small JSON helpers
#

output=human
[ "$raw" ] && output=raw
[ "$trame" ] && output=trame

# JSON-escape (busybox sed): same shape as spk-search/spk-doctor.
json_escape() {
	printf '%s' "$1" | sed \
		-e 's/\\/\\\\/g' \
		-e 's/"/\\"/g' \
		-e 's/	/\\t/g' \
		-e 's/\r/\\r/g' \
		-e ':a;N;$!ba;s/\n/\\n/g'
}

# Emit one package object/row. trame uses a comma prefix mechanism
# (see open_trame / close_trame) so the caller manages [ , ] framing.
# Args: source pkg ver cat desc installed(true|false)
emit_pkg() {
	local _src="$1" pkg="$2" ver="$3" cat_="$4" desc="$5" inst="$6"
	case "$output" in
	raw)
		printf '%s\t%s\t%s\t%s\t%s\t%s\n' \
			"$_src" "$pkg" "$ver" "$cat_" "$inst" "$desc"
		;;
	trame)
		[ "$first" ] || printf ','
		first=
		printf '{"package":"%s","version":"%s","category":"%s","short_desc":"%s","installed":%s}' \
			"$(json_escape "$pkg")" "$(json_escape "$ver")" \
			"$(json_escape "$cat_")" "$(json_escape "$desc")" "$inst"
		;;
	esac
}

# Open / close the trame envelope. Source is one of:
# installed | mirror | extra | blocked
open_trame() {
	[ "$output" = trame ] || return 0
	printf '{"command":"ls","source":"%s","packages":[' "$1"
	first=yes
}
close_trame() {
	[ "$output" = trame ] || return 0
	printf '],"count":%s}\n' "${1:-0}"
}

#
# Handle --options
#

for opt in $@
do
	case "$opt" in
		*usage|*help) usage ;;
		--count)
			count_installed
			count_mirrored
			exit 0 ;;
		--mirror)
			if [ "$output" = human ]; then
				newline
				boldify $(gettext "Mirror") $(cat $mirrorurl)
				separator
				read_pkgsinfo $pkgsinfo
				separator
				boldify $(count_mirrored)
				newline && exit 0
			fi
			open_trame mirror
			n=0
			while IFS="	" read pkg ver cat_ desc rest; do
				[ -z "$pkg" ] && continue
				inst=false
				is_package_installed "$pkg" && inst=true
				emit_pkg mirror "$pkg" "$ver" "$cat_" "$desc" "$inst"
				n=$((n + 1))
			done < "$pkgsinfo"
			close_trame "$n"
			exit 0 ;;
		--extra)
				[ -d "$extradb" ] || exit 1
				for extra in $extradb/*
				do
					newline
					boldify $(gettext "Extra mirror")
					if [ ! -f "$extra/packages.info" ]; then
						echo "URL: $(cat $extra/mirror)"
						gettext "Missing:"; colorize 31 " packages.info"
						continue
					fi
					separator
					read_pkgsinfo $extra/packages.info
					separator
					boldify $(echo -n $(cat $extra/packages.$SUM | wc -l))
					gettext "packages in:"; echo " $(basename $extra)"
					newline
				done
				exit 0 ;;
		--blocked)
			if [ "$output" = human ]; then
				if [ -s "$blocked" ]; then
					cat $blocked
				else
					gettext "No blocked packages"; newline
				fi
				exit 0
			fi
			open_trame blocked
			n=0
			if [ -s "$blocked" ]; then
				while IFS= read -r pkg; do
					[ -z "$pkg" ] && continue
					inst=false
					is_package_installed "$pkg" && inst=true
					emit_pkg blocked "$pkg" "" "" "" "$inst"
					n=$((n + 1))
				done < "$blocked"
			fi
			close_trame "$n"
			exit 0 ;;
		--short)
			if [ "$output" = human ]; then
				newline
				echo -n $(boldify $(gettext "Package"))
				indent 28 $(boldify $(gettext "Version"))
				separator
				for pkg in $(ls -1 $installed)
				do
					source_receipt $installed/$pkg/receipt
					echo $(colorize 32 $pkg) $(indent 28 "$VERSION")
				done
				separator
				boldify $(count_installed)
				newline
				exit 0
			fi
			open_trame installed
			n=0
			for pkg in $(ls -1 $installed); do
				unset_receipt
				source_receipt $installed/$pkg/receipt
				emit_pkg installed "$PACKAGE" \
					"${VERSION}${EXTRAVERSION}" \
					"$CATEGORY" "$SHORT_DESC" true
				n=$((n + 1))
			done
			close_trame "$n"
			exit 0 ;;
		--*) continue ;;
		*)
			# List installed files by the package.
			count=0
			for pkg in $@
			do
				[ -f "$installed/$pkg/files.list" ] || continue
				nb=$(cat $installed/$pkg/files.list | wc -l)
				count=$(($count + 1))
				[ "$count" = 1 ] && newline
				# List modifiers
				if [ "$modifiers" ]; then
					modifiers=$installed/$pkg/modifiers
					if [ -f "$modifiers" ]; then
						boldify $(gettext "Modifiers for") $pkg
						separator
						cat $modifiers
						separator && newline
					else
						echo $(boldify $pkg) $(gettext "package was not modified")
					fi
					continue
				fi
				boldify $(gettext "Installed files by") $pkg
				separator
				cat $installed/$pkg/files.list
				separator
				gettext "Installed files by"; echo -n " $pkg: "
				colorize 32 "$nb" && newline
			done
			exit 0 ;;
	esac
done

#
# Parse all installed pkgs receipt.
#

count=0

if [ "$output" = human ]; then
	newline
	boldify $(gettext "Installed packages")
	separator
	for pkg in $installed/*
	do
		unset_receipt
		source_receipt $pkg/receipt
		count=$(($count + 1))
		[ "$count" != 1 ] && newline
		gettext "Package    :"; colorize 32 " $PACKAGE"
		receipt_info
	done
	separator
	boldify $(count_installed) && newline
	exit 0
fi

# raw / trame: emit the installed list as a flat array.
open_trame installed
for pkg in $installed/*; do
	unset_receipt
	source_receipt $pkg/receipt
	emit_pkg installed "$PACKAGE" \
		"${VERSION}${EXTRAVERSION}" \
		"$CATEGORY" "$SHORT_DESC" true
	count=$((count + 1))
done
close_trame "$count"
exit 0
