#!/bin/bash
SCRIPTDIR="$(dirname $(which "${0}"))"

OPTIND=1
while getopts ":s:mxg" OPT ; do
    case "${OPT}" in
        s) START_TIME="${OPTARG}";;
        m) MASK_ONLY="Y" ;;
        x) ERROR_REVIEW="Y" ;;
        g) GIF_OUTPUT="Y" ;;
        *) echo "bad option -${OPTARG}" ; _usage ;;
        :) echo "Option -${OPTARG} requires an argument" ; exit 1 ;;
    esac
done
shift $(( ${OPTIND} - 1 ))

if [[ -n "${START_TIME}" ]] ; then
  INPUT_OPTS+=(-ss "${START_TIME}")
fi

# fill color handling
_convert_array_to_macroblock(){
  LUMA_AC="ffffffffffffffffffffff"
  CHROMA_AC="ffffffffffffff"
  COLOR_POINT="${1}"
  echo "${COLOR_POINT:0:6}${LUMA_AC}${COLOR_POINT:0:6}${LUMA_AC}${COLOR_POINT:0:6}${LUMA_AC}${COLOR_POINT:0:6}${LUMA_AC}${COLOR_POINT:6:6}${CHROMA_AC}${COLOR_POINT:12:6}${CHROMA_AC}"
  # get dv color data via
  # ffmpeg -f lavfi -i color=s=720x480:r=30000/1001:color=yellow -vframes 1 -f rawvideo -c:v dvvideo -pix_fmt yuv411p - | xxd -ps -c 80 | tail -n 1 | cut -c 9-14,121-126,141-146
}

# font selection
if [[ -f "/Library/Fonts/Andale Mono.ttf" ]] ; then
  DEFAULTFONT="/Library/Fonts/Andale Mono.ttf"
elif [[ -f "/System/Library/Fonts/Supplemental/Andale Mono.ttf" ]] ; then
  DEFAULTFONT="/System/Library/Fonts/Supplemental/Andale Mono.ttf"
elif [[ -f "/System/Library/Fonts/Monaco.dfont" ]] ; then
  DEFAULTFONT="/System/Library/Fonts/Monaco.dfont"
elif [[ -f "/Library/Fonts/Microsoft/Lucida Console.ttf" ]] ; then
  DEFAULTFONT="/Library/Fonts/Microsoft/Lucida\Console.ttf"
elif [[ -f "/Library/Fonts/LetterGothicStd.otf" ]] ; then
  DEFAULTFONT="/Library/Fonts/LetterGothicStd.otf"
else
  _report -wt "$(basename "${0}") can't find a preferred font to use :("
fi

DV_YELLOW="5206ff1216ff9016ff"
DV_RED="d106ff7016ffda16ff"
FILL=$(_convert_array_to_macroblock "${DV_YELLOW}")
if [[ "${MASK_ONLY}" = "Y" ]] ; then
  FIND="(?<=9[0-9a-f]{5}[0][0-9a-f])[0-9a-f]{152}"
else
  FIND="(?<=9[0-9a-f]{5}[^0][0-9a-f])[0-9a-f]{152}"
fi

# filter handling
TILE_V="8"
TILE_H="4"
LESSONE="$((${TILE_V}*${TILE_H}-1))"
FILTER="scale=iw/4:ih/4,transpose=2,tile=layout=${TILE_V}x${TILE_H}:init_padding=${LESSONE}:overlap=${LESSONE}:padding=1,transpose=1,setsar=1/1"

_play_dv(){
  ffmpeg "${INPUT_OPTS[@]}" -i "${1}" -c:v copy -f rawvideo - | \
  xxd -p -c 80 | \
  perl -pe "s|${FIND}|${FILL}|g" | \
  xxd -r -p | \
  ffplay - -vf "${FILTER}"
}

_make_dvrescue_xml(){
  if [[ ! -f "${DVRESCUE_XML}" ]] ; then
    echo "Assessing $(basename "${DVFILE}")..."
    _mkdir2 "${SIDECAR_DIR}"
    dvrescue "${DVFILE}" > "${DVRESCUE_XML}"
  fi
}

_maketemp(){
    mktemp -q "/tmp/$(basename "${0}").XXXXXX"
    if [ "${?}" -ne 0 ]; then
        echo "${0}: Can't create temp file, exiting..."
        _writeerrorlog "_maketemp" "was unable to create the temp file, so the script had to exit."
        exit 1
    fi
}

_mkdir2(){
    local DIR2MAKE=""
    while [ "${*}" != "" ] ; do
        DIR2MAKE="${1}"
        if [ ! -d "${DIR2MAKE}" ] ; then
            mkdir -p "${DIR2MAKE}"
            if [ "${?}" -ne 0 ]; then
                _report -wt "${0}: Can't create directory at ${DIR2MAKE}"
                exit 1
            fi
        fi
        shift
    done
}

while [[ "${@}" != "" ]] ; do
  DVFILE="${1}"
  shift
  BASENAME="$(basename "${DVFILE}")"
  SIDECAR_DIR="${DVFILE}_dvrescue"
  DVRESCUE_XML="${SIDECAR_DIR}/${BASENAME}.dvrescue.xml"

  if [[ "${ERROR_REVIEW}" = "Y" ]] || [[ "${GIF_OUTPUT}" = "Y" ]] ; then
    _make_dvrescue_xml
    echo "Making jpegs of errors within $(basename "${DVFILE}")..."
    TOTAL_FRAMES="$(xmlstarlet sel -N d="https://mediaarea.net/dvrescue" -t -m "d:dvrescue/d:media" -v "sum(d:frames/@count)" -n "${DVRESCUE_XML}")"
    COUNTER=1
    xmlstarlet sel -N d="https://mediaarea.net/dvrescue" -t -m "d:dvrescue/d:media/d:frames/d:frame[d:sta]" -v @n -o "," -v @pts -o "," -v @tc -n "${DVRESCUE_XML}" | while read error_frame ; do
      N="$(echo "${error_frame}" | cut -d "," -f1)"
      PTS="$(echo "${error_frame}" | cut -d "," -f2)"
      TC="$(echo "${error_frame}" | cut -d "," -f3)"
      TC_FILENAME_SAFE="$(echo "${TC}" | sed 's|:|-|g')"
      PTS_C="$(echo "${PTS}" | sed 's|:|-|g')"
      PTS_E="$(echo "${PTS}" | sed 's|:|\\:|g')"
      TC_E="$(echo "${TC}" | sed 's|:|\\:|g')"
      if [[ "${GIF_OUTPUT}" = "Y" ]] ; then
        _mkdir2 "${SIDECAR_DIR}/dvrescue_tmp"
        JPG_OUTPUT="${SIDECAR_DIR}/dvrescue_tmp/${BASENAME}_$(echo "$COUNTER" | awk '{ printf("%06i", $1) }').jpg"
      else
        JPG_OUTPUT="${SIDECAR_DIR}/${BASENAME}_${TC_FILENAME_SAFE}.jpg"
      fi
      ffmpeg -ss "${PTS}" -i "${DVFILE}" -vframes:v 1 -c:v copy -f rawvideo - | \
      xxd -p -c 80 | \
      perl -pe "s|${FIND}|${FILL}|g" | \
      xxd -r -p | \
      ffmpeg -y -i - -vf "pad=w=iw:h=ih+24:x=0:y=24:color=gray,drawbox=t=fill:w=iw*(${N}/${TOTAL_FRAMES}):h=24:c=silver:x=0:y=0,drawtext=fontfile=${DEFAULTFONT}:y=4:x=4:text='PTS=${PTS_E} TC=${TC_E} Frame=${N}'" "${JPG_OUTPUT}"
      ((COUNTER=COUNTER+1))
    done
    if [[ "${GIF_OUTPUT}" = "Y" ]] ; then
      GIF_PALETTE="$(_maketemp)"
      ffmpeg -nostdin -f image2 -i "${SIDECAR_DIR}/dvrescue_tmp/${BASENAME}_%06d.jpg" -vf palettegen "${GIF_PALETTE}.png"
      ffmpeg -nostdin -f image2 -i "${SIDECAR_DIR}/dvrescue_tmp/${BASENAME}_%06d.jpg" -i "${GIF_PALETTE}.png" -filter_complex paletteuse "${SIDECAR_DIR}/${BASENAME}_error.gif"
      rm -r "${SIDECAR_DIR}/dvrescue_tmp" "${GIF_PALETTE}.png"
    fi
  else
    _play_dv "${DVFILE}"
  fi
done
