#!/bin/bash

setupDestination() {
	cat <<-EODesc

        Format:
            copy, vorbis, opus or mp3. Other formats may appear in the future.
	EODesc
	comeagain() {
		read						\
			-e					\
			${destinationformat["$destination"]+-i"${destinationformat["$destination"]}"}\
			-p 'Format: '				\
			value
		case "$value" in
			'mp3')
				destinationformat["$destination"]=mp3
				lameneeded=1
			;;
			'opus')
				destinationformat["$destination"]=opus
				opusencneeded=1
			;;
			'vorbis'|'ogg')
				destinationformat["$destination"]=vorbis
				oggencneeded=1
			;;
			'copy')
				destinationformat["$destination"]=copy
			;;
			*)
				echo "Unsupported destination format: $value" >&2
				comeagain
			;;
		esac
	}
	comeagain
	cat <<-EODesc

        Path (path):
            Where to store transcoded files (will be created if it does not
            exist).
	EODesc
	read							\
		-e						\
		-p'Path: '					\
		${destinationpath["$destination"]+-i"${destinationpath["$destination"]}"}\
		destinationpath["$destination"]
	case ${destinationformat["$destination"]} in
		copy)
			:
		;;
		vorbis)
			cat <<-EODesc

        Quality (integer):
            The quality parameter of oggenc. See man oggenc for more info.
			EODesc
			expr='^[0-9]*$'
			comeagain() {
				read 					\
					-p'Quality: '			\
					-e				\
					-i				\
					${destinationquality["$destination"]:-3}\
					value
				if ! [[ $value =~ $expr ]]
				then
					echo "Invalid quality value: $value" >&2
					comeagain
				fi
			}
			comeagain
			if [ -n "${destinationquality["$destination"]}" ] \
			&& (( value != ${destinationquality["$destination"]} ))
			then
				setupRegen quality
			fi
			destinationquality["$destination"]=$value
		;;
		opus)
			cat <<-EODesc

        Bitrate (kbps, integer):
            Set (VBR) bitrate to <bitrate>. Note that while Opus allows for
            decimal values, AtOM does not. The reason for this is simple: we do
            numeric comparisons, and Bash only manipulates integers.
			EODesc
			expr='^[0-9]*$'
			comeagain() {
				read					\
					-e				\
					-i				\
					${destinationquality["$destination"]:-128}\
					-p 'Bitrate: '			\
					value
				if ! [[ $value =~ $expr ]]
				then
					echo "Invalid bitrate value: $value" >&2
					comeagain
				fi
			}
			comeagain
			if [ -n "${destinationquality["$destination"]}" ] \
			&& (( value != ${destinationquality["$destination"]} ))
			then
				setupRegen bitrate
			fi
			destinationquality["$destination"]=$value
			cat <<-EODesc

        Loss (percent, integer):
            If you intend to stream the resulting files over an unreliable
            protocol, you may want to make use of Opus' Forward Error
            Correction algorythm. See the Opus-codec.org website for details.
			EODesc
			comeagain() {
				read					\
					-e				\
					-i				\
					${destinationloss["$destination"]:-0}\
					-p 'Loss: '			\
					value
				if ! [[ $value =~ $expr ]]
				then
					echo "Invalid loss value: $value" >&2
					comeagain
				fi
			}
			comeagain
			if [ -n "${destinationloss["$destination"]}" ] \
			&& (( value != ${destinationloss["$destination"]} ))
			then
				setupRegen loss
			fi
			destinationloss["$destination"]=$value
		;;
		mp3)
			cat <<-EODesc

        Bitrate (kbps, integer):
            Set (ABR) bitrate to <bitrate>.
			EODesc
			expr='^[0-9]*$'
			comeagain() {
				read					\
					-e				\
					-i				\
					${destinationquality["$destination"]:-128}\
					-p 'Bitrate: '			\
					value
				if ! [[ $value =~ $expr ]]
				then
					echo "Invalid bitrate value: $value" >&2
					comeagain
				fi
			}
			comeagain
			if [ -n "${destinationquality["$destination"]}" ] \
			&& (( value != ${destinationquality["$destination"]} ))
			then
				setupRegen bitrate
			fi
			destinationquality["$destination"]=$value
			cat <<-EODesc

        Prevent resampling (boolean):
            LAME may decide to encode your file to a lower sampling-rate if you
            use a low bitrate. Setting this to yes will append --resample
            <original file's rate>, preventing any resampling from happening.
			EODesc
			case ${destinationnoresample["$destination"]} in
				0)	initialvalue=n		;;
				1)	initialvalue=y		;;
				*)	unset initialvalue	;;
			esac
			comeagain() {
				read					\
					-e				\
					${initialvalue+-i $initialvalue}\
					-p'Prevent resampling (y/N): '	\
					value
				case $value in
					[yY])
						[[ $initialvalue == n ]]\
						&& setupRegen noresample
						destinationnoresample["$destination"]=1
					;;
					''|[nN])
						[[ $initialvalue == y ]]\
						&& setupRegen noresample
						destinationnoresample["$destination"]=0
					;;
					*)
						comeagain
					;;
				esac
			}
			comeagain
		;;
	esac
	cat <<-EODesc

        [Optional parameters]
            Now you will have the opportunity to configure "advanced" parameters
            for $destination. You may leave any of these fields blank.
	EODesc
	if [[ ${destinationformat["$destination"]} != copy ]]
	then
		cat <<-EODesc

		Normalize (boolean):
		    Normalize output files.
		EODesc
		case ${destinationnormalize["$destination"]} in
			0)	initialvalue=n		;;
			1)	initialvalue=y		;;
			*)	unset initialvalue	;;
		esac
		comeagain() {
			read					\
				-e				\
				${initialvalue+-i $initialvalue}\
				-p'Normalize (y/N): '		\
				value
			case $value in
				[yY])
					[[ $initialvalue == n ]]	\
					&& setupRegen normalize
					destinationnormalize["$destination"]=1
				;;
				''|[nN])
					[[ $initialvalue == y ]]	\
					&& setupRegen normalize
					destinationnormalize["$destination"]=0
				;;
				*)
					comeagain
				;;
			esac
		}
		comeagain
	fi
	cat <<-EODesc

        Rename (string):
            Destination files will be named according to <string>, after
            expansion of special strings:
                %{album},
                %{albumartist},
                %{artist},
                %{disc},
                %{genre},
		%{releasecountry},
                %{title},
                %{track},
                %{year}.
            Untagged files or files in unrecognized formats will not be changed.
            Surrounding a field with [] makes it optional, meaning renaming
            will still happen if the corresponding tag is not defined.

            Leave blank if you don't want file renaming.
	EODesc
	initialvalue="${destinationrenamepath["$destination"]}"
	initialvalue+=/
	[[ $initialvalue == / ]] && unset initialvalue
	initialvalue+="${destinationrename["$destination"]}"
	[ -z "$initialvalue" ] && unset initialvalue
	read						\
		-e					\
		${initialvalue+-i"$initialvalue"}	\
		-p'Rename pattern: '			\
		value
	if [[ $value =~ / ]]
	then
		destinationrenamepath["$destination"]="${value%/*}"
	fi
	destinationrename["$destination"]="${value##*/}"
	cat <<-EODesc

        FAT32 Compatibility (boolean):
            Rename files for compatibility with FAT32 filesystems.
	EODesc
	case ${destinationfat32compat["$destination"]} in
		0)	initialvalue=n		;;
		1)	initialvalue=y		;;
		*)	unset initialvalue	;;
	esac
	comeagain() {
		read					\
			-e				\
			${initialvalue+-i $initialvalue}\
			-p'FAT32 Compatibility (y/N): '		\
			value
		case $value in
			[yY])
				destinationfat32compat["$destination"]=1
			;;
			''|[nN])
				destinationfat32compat["$destination"]=0
			;;
			*)
				comeagain
			;;
		esac
	}
	comeagain
	cat <<-EODesc

        ASCII-only filenames (boolean):
            Rename files for compatibility with ASCII-only systems (most car
	    radios).
             Uses Perl with Text::Unidecode to replace cyrillic or kanji
             with an ASCII representation.
	EODesc
	case ${destinationascii["$destination"]} in
		0)	initialvalue=n		;;
		1)	initialvalue=y		;;
		*)	unset initialvalue	;;
	esac
	comeagain() {
		read					\
			-e				\
			${initialvalue+-i $initialvalue}\
			-p'ASCII-only filenames (y/N): '\
			value
		case $value in
			[yY])
				destinationascii["$destination"]=1
			;;
			''|[nN])
				destinationascii["$destination"]=0
			;;
			*)
				comeagain
			;;
		esac
	}
	comeagain
	cat <<-EODesc

        Skip mime-type (mime-type, string):
            Files with mime-type <mime-type> will not be included in that
            destination. The '*' character is a wildcard.

            This prompt will loop until an empty string is encountered.
	EODesc
	while [[ ${destinationskipmime["$destination"]} =~ \| ]]
	do
		skippedmimes+=("${destinationskipmime["$destination"]%%|*}")
		destinationskipmime["$destination"]="${destinationskipmime["$destination"]#*|}"
	done
	[ -n "${destinationskipmime["$destination"]}" ]			\
	&& skippedmimes+=("${destinationskipmime["$destination"]}")
	count=${#skippedmimes[@]}
	unset destinationskipmime["$destination"]
	for (( i=0 ; 1 ; i++ ))
	do
		read							\
			-e						\
			${skippedmimes[i]+-i"${skippedmimes[i]}"}	\
			-p 'Skip mime-type: '				\
			value
		if [ -n "$value" ]
		then
			destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
		elif (( i < count ))
		then
			continue
		else
			break
		fi
	done
	unset skippedmimes
	if [[ ${destinationformat["$destination"]} != copy ]]
	then
		cat <<-EODesc

		Copy mime-type (mime-type, string):
		    Files with mime-type <mime-type> will be copied as-is to the
		    destination. E.g. image/* will copy covers and other images to the
		    destination.  The '*' character is a wildcard.

		    This prompt will loop until an empty string is encountered.
		EODesc
		while [[ ${destinationcopymime["$destination"]} =~ \| ]]
		do
			copiedmimes+=("${destinationcopymime["$destination"]%%|*}")
			destinationcopymime["$destination"]="${destinationcopymime["$destination"]#*|}"
		done
		[ -n "${destinationcopymime["$destination"]}" ]		\
		&& copiedmimes+=("${destinationcopymime["$destination"]}")
		count=${#copiedmimes[@]}
		unset destinationcopymime["$destination"]
		for (( i=0 ; 1 ; i++ ))
		do
			read						\
				-e					\
				${copiedmimes[i]+-i"${copiedmimes[i]}"}	\
				-p 'Copy mime-type: '			\
				value
			if [ -n "$value" ]
			then
				destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
			elif (( i < count ))
			then
				continue
			else
				break
			fi
		done
		unset copiedmimes

		cat <<-EODesc

		Copy extensions (extension, string):
		    Files with extension <extension> will be copied as-is to the
		    destination. E.g. .jpg will copy covers and other images to the
		    destination.

		    This prompt will loop until an empty string is encountered.
		EODesc
		while [[ ${destinationcopyext["$destination"]} =~ \| ]]
		do
			copiedexts+=("${destinationcopyext["$destination"]%%|*}")
			destinationcopyext["$destination"]="${destinationcopyext["$destination"]#*|}"
		done
		[ -n "${destinationcopyext["$destination"]}" ]		\
		&& copiedexts+=("${destinationcopyext["$destination"]}")
		count=${#copiedexts[@]}
		unset destinationcopyext["$destination"]
		for (( i=0 ; 1 ; i++ ))
		do
			read						\
				-e					\
				${copiedexts[i]+-i"${copiedexts[i]}"}	\
				-p 'Copy extension: '			\
				value
			if [ -n "$value" ]
			then
				destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
			elif (( i < count ))
			then
				continue
			else
				break
			fi
		done
		unset copiedexts

		cat <<-EODesc

		Channels (integer):
		    Produced files should have this many channels, no more, no less.
		EODesc
		expr='^[0-9]*$'
		comeagain() {
			read							\
				-e						\
				${destinationchannels["$destination"]+-i${destinationchannels["$destination"]}}\
				-p'Channel count: '				\
				value
			if ! [[ $value =~ $expr ]]
			then
				echo "Invalid channel count: $value" >&2
				comeagain
			fi
		}
		comeagain
		if [ -n "${destinationchannels["$destination"]}" ] \
		&& (( value != ${destinationchannels["$destination"]} ))
		then
			setupRegen channels
		fi
		destinationchannels["$destination"]=$value
		cat <<-EODesc

		Sampling rate (Hertz, integer):
		    Files will be resampled as needed to the specified sampling-rate.
		    Shoutcast/Icecast streams require a constant sampling-rate.
		    Telephony systems often require a sampling-rate of 8000Hz.
		EODesc
		if [[ ${destinationformat["$destination"]} == opus ]]
		then
			cat <<-EODesc

			Please note that Opus supports only the following sample-rates:
			8000, 12000, 16000, 24000, and 48000 Hz. So don't set
			resampling on an Opus destination to any other value or files
			will be resampled twice.
			EODesc
		fi
		comeagain() {
			read							\
				-e						\
				${destinationfrequency["$destination"]+-i${destinationfrequency["$destination"]}}\
				-p'Sampling-rate: '				\
				value
			if ! [[ $value =~ $expr ]]
			then
				echo "Invalid frequency value: $value" >&2
				comeagain
			fi
		}
		comeagain
		if [ -n "${destinationfrequency["$destination"]}" ] \
		&& (( value != ${destinationfrequency["$destination"]} ))
		then
			setupRegen frequency
		fi
		destinationfrequency["$destination"]=$value
		cat <<-EODesc

		Higher-Than (bitrate, integer):
		    Only reencode files with bitrates higher then <bitrate>kbps. This
		    only applies if sample-rate, channel count and of course format are
		    equal. If unset, only files with bitrates equal to that of the
		    target will be copied (actually, hardlinking will be attempted
		    first).

		    As Ogg Vorbis target quality is not defined by its bitrate, Ogg
		    Vorbis files will always be reencoded if unset.
		EODesc
		comeagain() {
			read							\
				-e						\
				${destinationmaxbps["$destination"]+-i${destinationmaxbps["$destination"]}}\
				-p'Higher-Than: '				\
				value
			if ! [[ $value =~ $expr ]]
			then
				echo "Invalid higher-than bitrate value: $value" >&2
				comeagain
			fi
		}
		comeagain
		if [ -n "${destinationmaxbps["$destination"]}" ] \
		&& (( value != ${destinationmaxbps["$destination"]} ))
		then
			setupRegen maxbps
		fi
		destinationmaxbps[$destination]="$value"
		unset regen
		unset expr
	fi
}
