#!/usr/bin/zsh

help_args=(-h --help)
if [[ "${@:*help_args}" != "" ]] {
    cat <<-END
		ffmpeg-mka-thumbnailer
		Extract album cover art from Matroska audio files (.mka)

		Usage:
		  ffmpeg-mka-thumbnailer [OPTIONS] -i <INPUT FILE> -o <OUTPUT FILE>

		Options:
		  -h, --help		Show this help text
		  -i <INPUT FILE>	Matroska audio file to read
		  -o <OUTPUT FILE>	Where to write the output
		  -s <SIZE>		Not implemented yet
	END
    exit 1
}

required_args=(-i -o)
if [[ "${==${(o)@:*required_args}}" != "-i -o" ]] {
    supplied_args=("${@:*required_args}")
    for p ("${(@)required_args:|supplied_args}") {
        echo "Missing argument $p" >&2
    }
    exit 1
}

input=
output=

while [[ $# -gt 0 ]] {
    case "$1" {
        -i)
            input="$2"
            shift
            ;;
        -o)
            output="$2"
            shift
            ;;
        -s)
            echo "-s is not implemented yet" >&2
            exit 1
            ;;
        *)
            echo "Unrecognized option $1" >&2
            exit 1
            ;;
    }

    shift
}

if [[ ! (-r "$input" && -f "$input") ]] {
    echo "Input $input is not a readable file" >&2
    exit 1
}

dir="$(dirname "$output")"
if [[ ! (-d "$dir" && -w "$dir") ]] {
    echo "Output $output is not under a writable directory" >&2
    exit 1
}

function ffmpeg_with_args() {
    ffprobe -of json -v error -select_streams $1:m:filename -show_streams "$input"
}

JQ_SELECTOR='[.streams, inputs.streams] as $inputs | {streams: ($inputs[0] - $inputs[1] + $inputs[2])}'
attachment_streams="$(jq -c "$JQ_SELECTOR" <<(ffmpeg_with_args v) <<(ffmpeg_with_args V) <<(ffmpeg_with_args t))"

if [[ "$(echo -n "$attachment_streams" | jq ".streams | length")" -lt 1 ]] {
    echo "Input does not have any suitable attachment streams" >&2
    exit 1
}

JQ_SELECTOR='[.streams[] | select((.tags.filename | (startswith("cover") or startswith("small_cover"))) and (.tags.mimetype | startswith("image/")))] | sort_by(.index) | first | .tags.filename | strings'
attachment_filename="$(echo -n "$attachment_streams" | jq -r "$JQ_SELECTOR")"

JQ_SELECTOR="[.streams[] | select(.tags.filename == \"$attachment_filename\")] | first | .codec_type"
attachment_codec_type="$(echo -n "$attachment_streams" | jq -r "$JQ_SELECTOR")"

if [[ "$attachment_filename" = "" ]] {
    echo "No suitable attachment found" >&2
    exit 1
}

prev_pwd="$(pwd)"
tmpdir="$(mktemp -d)"
tmpdir_success=$?
if [[ $tmpdir_success -ne 0 ]] {
    echo "Could not create temporary directory" >&2
    exit 1
} else {
    cd "$tmpdir"
}

return_code=0
repeat 1 {
    if [[ "$attachment_codec_type" = "video" ]] {
        ffmpeg -v error -f matroska -i "$input" -map m:filename:"$attachment_filename" -c copy "$attachment_filename" || { return_code=$?; break }
    } else {
        ffmpeg -v error -dump_attachment:t "$attachment_filename" -f matroska -i "$input" -t 0 -f null null || { return_code=$?; break }
    }
    if [[ "${attachment_filename##*.}" = "${output##*.}" || ("${attachment_filename##*.}" =~ ^jpe?g$ && "${output##*.}" =~ ^jpe?g$) ]] {
        mv "$attachment_filename" "$output"
    } else {
        convert "$attachment_filename" "$output" || { return_code=$?; break }
    }
}
cd "$prev_pwd"
rm -rf "$tmpdir"
exit $return_code
