# Convert between different formats.
# Usage: transcode <FORMAT> [FILES]
transcode()
{
  local IFS=$'\n'
  local targets=("${@:2}")
  local format="${1}"
  local total=${#targets[@]}
  local count=0
  local failed=0

  # Report no format.
  if [[ "${format}" = "" ]]; then
    echo -e "${color_bred}No format specified.${color_default}"
    echo "Usage: transcode <FORMAT> [FILES]"
    return 2
  fi

  # All files by default.
  if [[ "${targets}" = "" ]]; then
    targets=($(ls --classify | grep -v /$))
    total=${#targets[@]}
  fi

  # Process.
  for target in "${targets[@]}"; do
    # Increment counter.
    ((count++))

    # Define context names and status.
    local from="${target##*.}"
    local to="${format}"
    local output="${target#../}"
    output="${output%.*}"
    output="${output}.${to}"
    local status="[${count}/${total}] ${target} -> ${output}"

    # Show status.
    echo -e "${status}"

    # Skip same format.
    [[ "${from}" = "${to}" ]] && continue

    # Support multiple inputs.
    [[ "${to}" = "mp3" ]] && from=""
    [[ "${to}" = "flac" ]] && from=""
    [[ "${to}" = "mka" ]] && from=""
    [[ "${to}" = "mkv" ]] && from=""

    # Send convert.
    case "${from}-${to}" in
      "gz-xz"|"tgz-txz")
        _transcode_gz-xz "${target}" "${output}"
        ;;
      "xz-gz"|"txz-tgz")
        _transcode_xz-gz "${target}" "${output}"
        ;;
      "-mp3")
        _transcode_mp3 "${target}" "${output}"
        ;;
      "-flac")
        _transcode_flac "${target}" "${output}"
        ;;
      "-mka")
        _transcode_mka "${target}" "${output}"
        ;;
      "-mkv")
        _transcode_mkv "${target}" "${output}"
        ;;
      *)
        echo -e "${color_yellow}Conversion ${target##*.}-${to} not supported.${color_default}"
        false
        ;;
    esac

    # Show error.
    if [[ ${?} != 0 ]]; then
      echo -e "${color_bred}${status}: Failed.${color_default}"
      ((failed++))
    fi
  done

  if [[ ${failed} != 0 ]]; then
    echo -e "${color_bred}Failed: ${failed}.${color_default}"
    false
  fi
}

_transcode_gz-xz()
{
  pv "${1}" | gzip -d | xz -9e > "${2}"
}

_transcode_xz-gz()
{
  pv "${1}" | xz -d | gzip -1 > "${2}"
}

_transcode_mp3()
{
  ffmpeg -i "${1}" -c:a libmp3lame -b:a 320k -f mp3 "${2}"
}

_transcode_flac()
{
  ffmpeg -i "${1}" -c:a flac -f flac "${2}"
}

_transcode_mka()
{
  ffmpeg -i "${1}" -c:a libopus -b:a 128k -vn "${2}"
}

_transcode_mkv()
{
  local keyint=$(_ffprobe_keyint "${1}")
  local braudio=$(_ffprobe_ba "${1}")
  [[ ${braudio} -gt 128 ]] && braudio=128

  ffmpeg -i "${1}" -c:a libopus -b:a ${braudio}k -c:v libsvtav1 -crf 30 -svtav1-params "fast-decode=1:tune=0" -preset 6 -pix_fmt yuv420p10le -g ${keyint} -vf "scale=-2:min'(1080,ih)'" "${2}"
}

_ffprobe_fps()
{
  local fps=$(ffprobe -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate "${1}")
  fps="${fps%%/*}"
  echo "${fps}"
}

_ffprobe_keyint()
{
  local fps=$(_ffprobe_fps "${1}")
  echo $((fps*5))
}

_ffprobe_ba()
{
  local ba=$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "${1}")
  echo $((ba/1024))
}

# Export.
export -f transcode _transcode_gz-xz _transcode_xz-gz _transcode_mp3 _transcode_flac _transcode_mka _transcode_mkv _ffprobe_keyint _ffprobe_ba _ffprobe_fps