#!/usr/bin/env bash
# Script to control mpd from dmenu
# mpdmenu -l will create a playlist from chosen artist then album
# mpdmenu -p will choose a song in the current playlist
# Separate mpdmenu from dmenu args with :: eg
# `mpdmenu -l :: -i` to create a playlist from
#    an album with case-insensitive matches

all_name='[ALL]'
mode=library

d_artist() {
    mpc list artist | sort -f | dmenu -p artist "${dmenu_args[@]}"
}

d_album() {
    local artist="$1"
    local albums

    mapfile -t albums < <(mpc list album artist "$artist")
    if (( ${#albums[@]} > 1 )) ; then
        {
            printf '%s\n' "$all_name"
            printf '%s\n' "${albums[@]}" | sort -f
        } | dmenu -p album "${dmenu_args[@]}"
    else
        # We only have one album, so just use that.
        printf '%s\n' "${albums[0]}"
    fi
}

d_playlist() {
    local format="%position% - %title% - %album% - %artist%"
    local track

    track=$(mpc playlist -f "$format" | dmenu -p track "${dmenu_args[@]}")
    printf '%s' "${track%% *}"
}

i=2

for arg do
    if [[ $arg == :: ]]; then
        dmenu_args=( "${@:$i}" )
        break
    fi

    case "$arg" in
        -l) mode=library ;;
        -p) mode=playlist ;;
    esac

    (( i++ ))
done

case "$mode" in
    library)
        artist=$(d_artist)
        [[ $artist ]] || exit 1

        album=$(d_album "$artist")
        [[ $album ]] || exit 2

        mpc clear
        if [[ $album == "$all_name" ]]; then
            mpc find artist "$artist" | sort | mpc add
        else
            mpc find artist "$artist" album "$album" | sort | mpc add
        fi

        mpc play >/dev/null 2>&1
    ;;
    playlist)
        mpc play "$(d_playlist)"
    ;;
esac
