#!/bin/bash -
#===============================================================================
#
#         FILE: past_upload
#
#        USAGE: ./past_upload [-h] [-r] [-v] [-d {0|1}] start [count]
#
#  DESCRIPTION: Run the commands necessary to upload a batch of older HPR
#               shows to archive.org
#
#      OPTIONS: ---
# REQUIREMENTS: ---
#         BUGS: ---
#        NOTES: ---
#       AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com
#      VERSION: 0.0.12
#      CREATED: 2021-04-17 22:14:16
#     REVISION: 2022-07-07 16:17:41
#
#===============================================================================

set -o nounset                              # Treat unset variables as an error

SCRIPT=${0##*/}
# DIR=${0%/*}
VERSION="0.0.12"

STDOUT="/dev/fd/2"

#
# Select the appropriate working directory
#
case $(hostname) in
    i7-desktop)
        BASEDIR="$HOME/HPR/InternetArchive"
        UPLOAD="$BASEDIR/uploads"
        ;;
    borg)
        BASEDIR="$HOME/IA"
        UPLOAD="/data/IA/uploads"
        ;;
    *)
        echo "Wrong host!"
        exit 1
        ;;
esac

cd "$BASEDIR" || exit 1

#
# Load library functions
#
LIB="$HOME/bin/function_lib.sh"
[ -e "$LIB" ] || { echo "Unable to source functions"; exit; }
# shellcheck disable=SC1090
source "$LIB"

#
# Log file
#
LOGS="$BASEDIR/logs"
LOGFILE="$LOGS/$SCRIPT.log"

#
# Make temporary files and set traps to delete them
#
TMP1=$(mktemp) || { echo "$SCRIPT: creation of temporary file failed!"; exit 1; }
trap 'cleanup_temp $TMP1' SIGHUP SIGINT SIGPIPE SIGTERM EXIT

#===  FUNCTION  ================================================================
#         NAME: _verbose
#  DESCRIPTION: Writes a message in verbose mode
#   PARAMETERS: $1      message
#      RETURNS: Nothing
#===============================================================================
_verbose () {
    local msg=${1:-}

    [[ $VERBOSE -eq 1 ]] && echo "$msg"

}

#===  FUNCTION  ================================================================
#         NAME: _usage
#  DESCRIPTION: Reports usage; always exits the script after doing so
#   PARAMETERS: 1 - the integer to pass to the 'exit' command
#      RETURNS: Nothing
#===============================================================================
_usage () {
    local -i result=${1:-0}

    cat >$STDOUT <<-endusage
${SCRIPT} - version: ${VERSION}

Usage: ./${SCRIPT} [-h] [-r] [-v] [-d {0|1}] start [count]

Generates the necessary metadata and script and uses them to upload HPR audio
and other show-related files held on the VPS to the Internet Archive. This
script is similar to 'weekly_upload' but it's for dealing with older shows
where we only have the MP3 audio.

Options:
  -h                    Print this help
  -v                    Run in verbose mode where more information is reported
  -d 0|1                Dry run: -d 1 (the default) runs the script in dry-run
                        mode where nothing is changed but the actions that
                        will be taken are reported; -d 0 turns off dry-run
                        mode and the actions will be carried out.
  -F                    Force an upload even if the items are already on the
                        IA. Use with *GREAT* caution!
  -m                    Update the item's metadata from the file generated
                        for (re-)uploads. This ensures that any changes to the
                        notes, summary, tags, etc are propagated. This does
                        not happen by default, but shows with assets are
                        always updated this way.
  -r                    Run in 'remote' mode, using the live database over an
                        (already established) SSH tunnel. Default is to run
                        against the local database.
  -Y                    Answer 'Y' to the confirmation question (really don't
                        ask at all)

Arguments:
    start               the starting show number to be uploaded
    count               (optional, default 1) the number of shows to be
                        uploaded; not allowed to exceed 20

Notes:

1. When running on 'borg' the method used is to run in faux 'local' mode.
   This means we have an open tunnel to the HPR server (mostly left open) and
   the default file .hpr_db.cfg points to the live database via this tunnel.
   So we do not use the -r option here. This is a bit of a hack! Sorry!

TODO: Needs fix!

2. There are potential problems when a show has no tags which haven't been
   fully resolved. The make_metadata script fails in default mode when it
   finds such a show, but this (weekly_upload) script can continue on and run
   the generated script which uploads the source audio files. This can mean
   the IA items end up as books! In this mode the description is not stored
   and so there are no show notes.

endusage
    exit "$result"
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#
# Prerequisites
#
jq=$(command -v jq)
[ -z "$jq" ] && { echo "Needs the 'jq' JSON filter"; exit 1; }
ia=$(command -v ia)
[ -z "$ia" ] && { echo "Needs the 'ia' Internet Archive script"; exit 1; }
transfer_tags=$(command -v transfer_tags)
[ -z "$transfer_tags" ] && { echo "Needs the 'transfer_tags' script"; exit 1; }
tunnel_is_open=$(command -v tunnel_is_open)
[ -z "$tunnel_is_open" ] && { echo "Needs the 'tunnel_is_open' script"; exit 1; }
[ -e "$BASEDIR/transcode" ] || {
    echo "Needs the 'transcode' script"
    exit 1
}
[ -e "$BASEDIR/make_metadata" ] || {
    echo "Needs the 'make_metadata' script"
    exit 1
}

#
# Constant
#
RETRIES=5

#
# Check the tunnel is open
#
if ! tunnel_is_open; then
    echo "Open the tunnel before running this script (open_tunnel)"
    exit 1
fi

#-------------------------------------------------------------------------------
# Process options
#-------------------------------------------------------------------------------
while getopts :d:FhmrvY opt
do
    case "${opt}" in
        d) DRYRUN=$OPTARG;;
        F) FORCE=1;;
        h) _usage 1;;
        m) METADATA=1;;
        r) REMOTE=1;;
        v) VERBOSE=1;;
        Y) YES=1;;
        *) _usage 1;;
    esac
done
shift $((OPTIND - 1))

#
# Check choices and set defaults
#
DRYRUN=${DRYRUN:-1}
if [[ $DRYRUN -ne 0 && $DRYRUN -ne 1 ]]; then
    echo "** Use '-d 0' or '-d 1'"
    _usage 1
fi

FORCE=${FORCE:-0}

METADATA=${METADATA:-0}

YES=${YES:-0}

VERBOSE=${VERBOSE:-0}

REMOTE=${REMOTE:-0}
if [[ $REMOTE -eq 0 ]]; then
    dbconfig="$BASEDIR/.hpr_db.cfg"
    _verbose "Local database mode"
else
    dbconfig="$BASEDIR/.hpr_livedb.cfg"
    _verbose "Remote database mode"
fi

#
# Check argument count
#
if [[ ! ( $# -eq 1 || $# -eq 2 ) ]]; then
    echo "Wrong number of arguments"
    _usage 1
fi

#
# Validate arguments
#
for arg; do
    if [[ ! $arg =~ ^[0-9]{1,4}$ ]]; then
        echo "Invalid number: $arg"
        echo "Use a plain number"
        exit 1
    fi
done

#
# Set variables for the range of shows
#
start=$1
count=${2:-1}
if [[ $count -gt 20 ]]; then
    echo "Can't process more than 20 shows at a time"
    exit 1
fi
((end = start + count - 1))

[[ $DRYRUN -eq 1 ]] && _verbose "Dry run mode"

if [[ $VERBOSE -eq 1 ]]; then
    echo "Processing $count $(ngettext show shows "$count") from $start"
else
    echo "${start}..${end}"
fi

#
# Log the start of this run
#
[[ $DRYRUN -eq 0 ]] && \
    echo "$(date +%Y%m%d%H%M%S) Processing ${start}..${end} (v$VERSION)" >> "$LOGFILE"

#
# Store the show numbers in an array. We need 'eval' to substitute `$start'
# and '$end' for the 'printf'.
#
declare -a shows
mapfile -t shows < <(eval "printf '%04d\n' {$start..$end}")

#
# Walk the array and delete elements that are already on the IA
#
if [[ $FORCE -eq 1 ]]; then
    _verbose 'Not checking for shows on archive.org; forcing!'
    [[ $DRYRUN -eq 0 ]] && echo "$(date +%Y%m%d%H%M%S) Forcing an update (-F)" >> "$LOGFILE"
else
    _verbose 'Checking for shows on archive.org'
    [[ $DRYRUN -eq 0 ]] && echo "$(date +%Y%m%d%H%M%S) Checking archive.org" >> "$LOGFILE"
    i=0
    for item in "${shows[@]}"; do
        if ia list "hpr$item" > /dev/null 2>&1; then
            _verbose "Found hpr$item on archive.org"
            unset "shows[$i]"
        fi
        ((i++))
        done
fi

#
# Stop if there's nothing to do
#
if [[ ${#shows[@]} -eq 0 ]]; then
    echo "Nothing to do; nominated show(s) are currently on archive.org"
    [[ $DRYRUN -eq 0 ]] && echo "$(date +%Y%m%d%H%M%S) Nothing to do" >> "$LOGFILE"
    exit 1
else
    _verbose "There $(ngettext 'is 1 show' "are ${#shows[@]} shows" "${#shows[@]}") to process"
fi

#
# Find which audio needs to be downloaded and go get it
#
_verbose "Downloading missing audio..."
if [[ $DRYRUN -eq 1 ]]; then
    echo "Would have attempted to download ${#shows[@]} $(ngettext show shows "${#shows[@]}") (dry run)"
else
    for item in "${shows[@]}"; do
        if [[ ! -e $UPLOAD/hpr$item.mp3 ]]; then
            echo "Downloading hpr$item.mp3"
            wget -q "http://hackerpublicradio.org/local/hpr$item.mp3" \
                -O "$UPLOAD/hpr$item.mp3"
            _verbose "Downloaded $UPLOAD/hpr$item.mp3"
        else
            _verbose "$UPLOAD/hpr$item.mp3 already exists"
        fi
    done
fi

#
# Transcode the audio as needed
#
_verbose "Transcoding missing audio..."
if [[ $DRYRUN -eq 1 ]]; then
    echo "Would have transcoded ${#shows[@]} $(ngettext show shows "${#shows[@]}") (dry run)"
else
    [[ $DRYRUN -eq 0 ]] && \
        echo "$(date +%Y%m%d%H%M%S) Transcoding ${#shows[@]} $(ngettext show shows "${#shows[@]}")" >> "$LOGFILE"
    for item in "${shows[@]}"; do
        if [[ $VERBOSE -eq 1 ]]; then
            ./transcode -v "$UPLOAD/hpr$item.mp3"
        else
            ./transcode "$UPLOAD/hpr$item.mp3"
        fi
    done
fi

#
# We now have a list of shows in the right state to be uploaded, so we can do
# what's necessary
#
_verbose "Uploading $(ngettext show shows "${#shows[@]}")..."

#
# Define files for make_metadata. For aesthetic reasons don't use '1-1' when
# there's only one show!
#
if [[ $start -eq $end ]]; then
    printf -v metadata 'metadata_%04d.csv' "$start"
    printf -v script 'script_%04d.sh' "$start"
else
    printf -v metadata 'metadata_%04d-%04d.csv' "$start" "$end"
    printf -v script 'script_%04d-%04d.sh' "$start" "$end"
fi

#
# Check on the dry-run choice
#
if [[ $DRYRUN -eq 1 ]]; then
    echo "Dry run: Would have uploaded $count $(ngettext show shows "$count") from $start"
    echo "Dry run: Would have created $metadata and $script"
    echo "Dry run: Would have uploaded $metadata and run $script"
    echo "Dry run: Would have used $dbconfig"
    echo -n "Dry run: Would have done metadata updates for "
    if [[ $METADATA -eq 0 ]]; then
       echo "shows with assets"
   else
       echo "all shows"
    fi
else
    #
    # Really do the upload
    #
    if [[ $start -eq $end ]]; then
        echo "Uploading $start"
    else
        echo "Uploading $start to $end inclusive"
    fi

    #
    # Implement the -Y (override) option
    #
    if [[ $YES -eq 1 ]]; then
        confirmed=1
    else
        echo "$(date +%Y%m%d%H%M%S) Waiting for confirmation" >> "$LOGFILE"
        if yes_no "OK to continue? %s " "N"; then
            confirmed=1
        else
            confirmed=0
        fi
    fi

    #---------------------------------------------------------------------------
    # Do the work
    #---------------------------------------------------------------------------
    if [[ $confirmed -eq 1 ]]; then
        # shellcheck disable=2086
        {
            #
            # Make the metadata
            #
            _verbose "Running make_metadata"
            $BASEDIR/make_metadata -dbconf=${dbconfig} \
                -from=$start -count=$count \
                -verb -out -script -a_count=$TMP1
            RES=$?

            #
            # If it all went OK perform the uploads, otherwise report the
            # problem(s)
            #
            if [[ $RES -eq 0 ]]; then
                _verbose "Uploading audio and any assets"
                ia upload --retries=$RETRIES --spreadsheet=${metadata} \
                    -H x-archive-keep-old-version:0 && \
                    [ -e $script ] && ./${script}
                echo "$(date +%Y%m%d%H%M%S) Uploaded shows" >> "$LOGFILE"
            else
                echo "Upload aborted due to errors"
                echo "$(date +%Y%m%d%H%M%S) Upload failed due to errors" >> "$LOGFILE"
                exit 1
            fi

            #
            # Update metadata for all shows if requested
            #
            if [[ $METADATA -eq 1 ]]; then
                _verbose "Uploading changed metadata"
                ia metadata --spreadsheet=${metadata}
                echo "$(date +%Y%m%d%H%M%S) Metadata uploaded for all shows" >> "$LOGFILE"
            else
                #
                # We aren't updating metadata for all, but if any shows had
                # assets we need to do metadata updates. The show details are
                # in the temporary file $TMP1
                #
                if [[ -s $TMP1 ]]; then
                    _verbose "Refreshing metadata for shows with assets"
                    declare -a mshows
                    mapfile -t mshows < <(cut -f1 -d' ' $TMP1 | sed -e 's/^hpr//' | sort)
                    mlist="${mshows[*]}"

                    if [[ ${#mshows[@]} -eq 1 ]]; then
                        printf -v metadata 'meta_metadata_%04d.csv' "${mshows[0]}"
                    else
                        printf -v metadata 'meta_metadata_%04d-%04d.csv' "${mshows[0]}" "${mshows[-1]}"
                    fi

                    _verbose "Regenerating metadata"
                    $BASEDIR/make_metadata -dbconf=${dbconfig} -list="${mlist/ /,}" \
                        -out=${metadata} -meta -noassets -verb
                    RES=$?

                    if [[ $RES -eq 0 ]]; then
                        _verbose "Uploading new metadata"
                        ia metadata --spreadsheet=${metadata}
                        echo "$(date +%Y%m%d%H%M%S) Metadata uploaded for eligible shows" >> "$LOGFILE"
                    else
                        echo "Metadata update aborted due to errors"
                        echo "$(date +%Y%m%d%H%M%S) Metadata upload failed due to errors" >> "$LOGFILE"
                        exit 1
                    fi
                fi
            fi
        }
    else
        echo "Not uploaded"
        echo "$(date +%Y%m%d%H%M%S) Upload aborted" >> "$LOGFILE"
    fi
fi

# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21