# Remux videos to include subtitle files of the same name.

RESULTS_DIRECTORY_NAME="_remux"
DEFAULT_LANGUAGE_CODE="eng"

# TODO: This needs to be used in the glob, but I don't know how.
VIDEO_EXTENSIONS="mkv,mp4,avi"

typeset -A LANGUAGE_NAMES
LANGUAGE_NAMES=( \
	'english' 'en' \
	)

_mkvmerge_add_subtitles_mkvmerge () {
	original_file="$1"
	results_directory="$2"
	partial_file="${results_directory}/${original_file:t:r}.mkv.part"
	complete_file="${results_directory}/${original_file:t:r}.mkv"
	subtitle_options_array=()

	mkdir -p "$results_directory"

	# Given a file name, find subtitles and determine their language.
	# The following patterns should be supported, with [basename] being the given filename's
	# basename.
	# * [basename].srt
	# * [basename].[language code].srt
	# * Subs/[track_number]_[language].srt
	# * Subs/[basename]/[track_number]_[language].srt

	# TODO: Support the other patterns listed in the above comment.
	video_basename="$1"

	# Include subtitles without language codes, assuming $DEFAULT_LANGUAGE_CODE is correct.
	# For example: [basename].srt
	uncoded_subtitle_name="${original_file:r}.srt"
	if [[ -f "$uncoded_subtitle_name" ]]; then
		subtitle_options_array+=("--language" "0:${DEFAULT_LANGUAGE_CODE}" "$uncoded_subtitle_name")
		echo "Found uncoded subtitle file ${uncoded_subtitle_name}, assuming \
			${DEFAULT_LANGUAGE_CODE}."
	fi

	# Include subtitles with language codes in their filenames.
	# For example [basename].[language code].srt
	coded_subtitle_files=(${original_file:r}.*.srt(N))
	if [[ ! -z $coded_subtitle_files ]]; then
		for fname in $coded_subtitle_files; do
			language_code="${${fname:r}:e}"
			subtitle_options_array+=("--language" "0:${language_code}" "$fname")
			echo "Found coded subtitle file ${fname} for language ${language_code}."
		done
	fi

	# Include subtitles in the Subs directory
	named_subtitle_files=(${original_file:h}/Subs/*.srt)
	if [[ ! -z $named_subtitle_files ]]; then
		existing_language_codes=()
		for fname in $named_subtitle_files; do
			file_basename=${fname:t}

			# determine language code from filenames like 2_English.srt
			# This character soup does three things
			#	* #[0-9]*_ removes the preceding track number, such as 2_ or 13_
			#	* :r removes the file extension
			#	* :l makes it all lowercase
			language_name="${${file_basename#[0-9]*_}:r:l}"
			echo "Found subtitle file ${fname}."

			if [[ $LANGUAGE_NAMES[$language_name] ]]; then
				language_code=$LANGUAGE_NAMES[$language_name]
				echo "Checking if subtitle file ${fname} is usable."

				# TODO: This is absolutely an ugly way to do this, but this is what works.
				if $(echo ${existing_language_codes} > grep ${language_code}); then
					subtitle_options_array+=("--language" "0:${language_code}" "$fname")
					existing_language_codes+=$language_code
					echo "Found ${language_code} subtitles at ${fname}."

				else
					echo "Duplicate subtitle files for ${language_code}."
					exit 1
				fi

			else
				echo "Unknown language name ${language_name}."
				exit 1
			fi
		done
	fi

	# Finally, actually mux all the subtitles in if there are any.
	if [[ "${#subtitle_options_array}" -eq 0 ]]; then
		echo "No subtitles found for file ${original_file}"
	else
		echo "Remuxing ${original_file}..."
		mkvmerge --quiet -o "$partial_file" "$original_file" ${^subtitle_options_array} \
			|| rm "$partial_file"
		echo "Done!"

		if [[ -e "$partial_file" ]]; then
			mv "$partial_file" "$complete_file"
		fi
	fi

	if [[ -e "$results_directory" ]]; then
		rmdir --ignore-fail-on-non-empty "$results_directory"
	fi

}

arg_file="$1"

if [[ -z "$arg_file" ]]; then
	arg_file=.
fi

if [[ -f "$arg_file" ]]; then
	destination="${arg_file:h}/${RESULTS_DIRECTORY_NAME}"
	_mkvmerge_add_subtitles_mkvmerge "$arg_file" "$destination"

elif [[ -d "$arg_file" ]]; then
	destination="${arg_file}/${RESULTS_DIRECTORY_NAME}"

	# List all the video files in an array for future expansions like:
	#	- A prompt before you commit to remuxing.
	#	- Removing items that are already completed.
	#	- Interactively discarding list items
	#	- etc.
	# TODO: Use $VIDEO_EXTENSIONS here instead of hard-coding extension names.
	files=($arg_file/*.{mkv,mp4,avi}(N))
	for fname in $files; do
		_mkvmerge_add_subtitles_mkvmerge "$fname" "$destination"
	done

else
	echo "mkvmerge-add-subtitles: Error:${arg_file} is not a file or directory."
fi

# vim:syntax=sh filetype=sh
