#!/bin/sh

ACONV_OUTDIR="./converted"
ACONV_CODEC="libopus"
ACONV_BITRATE="128k"
ACONV_CONTAINER="ogg"
ACONV_QUIET=0
ACONV_THREADS=$(nproc --ignore=2)

chk_command() {
	if ! command -v "$1" > /dev/null; then
		>&2 echo "error: command '$1' could not be found"
		exit 1
	fi
}

chk_command "ffmpeg"
chk_command "getopts"
chk_command "parallel"
chk_command "find"

usage() {
	printf "usage: aconv [-hs] [options] dir\n"
}

help() {
	printf "usage: aconv [-hs] [options] dir\n\n"
	printf "\t-h\t\tprint this message\n"
	printf "\t-q\t\tset quiet output (only errors)\n"
	printf "\t-o OUTDIR\tset the output directory\n"
	printf "\t-c CODEC\tset the output codec\n"
	printf "\t-C CONTAINER\tset the output container\n"
	printf "\t-b BITRATE\tset the output bitrate\n"
	printf "\t-j THREADS\tset the number of threads (default all but 2)\n"
}

while getopts "hqo:c:C:b:j:" arg > /dev/null; do
	case $arg in
		h)
			help
			exit 0
			;;
		q)
			ACONV_QUIET=1
			;;
		o)
			ACONV_OUTDIR=${OPTARG}
			;;
		c)
			ACONV_CODEC=${OPTARG}
			;;
		C)
			ACONV_CONTAINER=${OPTARG}
			;;
		b)
			ACONV_BITRATE=${OPTARG}
			;;
		j)
			ACONV_THREADS=${OPTARG}
			;;
		?)
			>&2 echo "error: unknown option"
			usage
			exit 1
			;;
	esac;
done;

ACONV_DIR=${@:$OPTIND:1}

if [ "$ACONV_DIR" = "" ]; then
	usage
	exit 1
fi

if [ ! -d "$ACONV_DIR" ]; then
	>&2 echo "error: input directory '$ACONV_DIR' does not exist"
	exit 1
fi


convert_file() {
	# get arguments
	file="$1"
	ext="$2"
	name=${file%.*};
	# print log
	if [ "$ACONV_QUIET" -eq 0 ]; then
		printf "\x1b[34m  CONV  \x1b[0m%s\n" "$ACONV_OUTDIR/$name.$ACONV_CONTAINER"
	fi
	# do the thing
	ffmpeg -nostdin -y -i "$file" -c:a "$ACONV_CODEC" -b:a "$ACONV_BITRATE" "$ACONV_OUTDIR/$name.$ACONV_CONTAINER" -loglevel fatal
}

export ACONV_OUTDIR
export ACONV_CODEC
export ACONV_BITRATE
export ACONV_CONTAINER
export ACONV_QUIET
export ACONV_THREADS
export -f convert_file

convert_type() {
	# get arguments
	dir="$1"
	ext="$2"
	# convert the files
	find "$dir" -type f -name "*.$ext" | parallel -j "$ACONV_THREADS" convert_file "{}" "$ext"
}

convert_dir() {
	# get arguments
	dir="$1"

	# make the output dirs
	find "$dir" -type d -print0 |xargs -0 -I{} mkdir -p "$ACONV_OUTDIR/{}"

	# convert the things
	convert_type "$dir" "mp3"
	convert_type "$dir" "m4a"
	convert_type "$dir" "ogg"
	convert_type "$dir" "flac"
	convert_type "$dir" "wav"
	convert_type "$dir" "avif"
}

# do the thing
convert_dir "$ACONV_DIR"