#!/usr/bin/env bash
set -euo pipefail
shopt -u patsub_replacement

die() {
    echo "Error: $1" >&2
    exit 1
}

command -v ffprobe >/dev/null || die "ffprobe required"
command -v sed     >/dev/null || die "sed required"

# Paths
readonly site_conf="site.conf"
readonly html_template="template.html"
readonly rss_template="template.xml"
readonly item_template="item.html"
readonly rss_item_template="item.xml"

# Checks
[[ -f "$site_conf"         ]] || die "missing $site_conf"
[[ -f "$html_template"     ]] || die "missing $html_template"
[[ -f "$rss_template"      ]] || die "missing $rss_template"
[[ -f "$item_template"     ]] || die "missing $item_template"
[[ -f "$rss_item_template" ]] || die "missing $rss_item_template"
[[ -d media                ]] || die "missing media/"

# Temp files
tmp_html_items=$(mktemp)
tmp_rss_items=$(mktemp)

trap 'rm -f "$tmp_html_items" "$tmp_rss_items"' EXIT

# Defaults
date_format="%d %b %Y"
recursive=false
order=reverse
url_base=""

# Read config
while IFS=':' read -r k v; do

    k=$(xargs <<< "$k")
    v=$(xargs <<< "$v")

    case "$k" in
        date_format) date_format="$v" ;;
        recursive)   recursive="${v,,}" ;;
        order)       order="${v,,}" ;;
        url)         url_base="$v" ;;
    esac

done < "$site_conf"

# Normalise site URL
url_base="${url_base%/}"

# Generated tag
generated=$(date -Ru)

# Sort direction
sort_args=()

[[ "$order" != "forward" ]] && sort_args+=("-r")

# Metadata helper
meta() {
    ffprobe -v error \
        -show_entries format_tags="$1" \
        -of default=noprint_wrappers=1:nokey=1 \
        "$2" 2>/dev/null || true
}

# HTML escape
escape_html() {
    sed \
        -e 's/&/\&amp;/g' \
        -e 's/</\&lt;/g' \
        -e 's/>/\&gt;/g'
}

# Linkify URLs
linkify() {
    sed -E 's@(https?://[^[:space:]<]+)@<a href="\1">\1</a>@g'
}

# Find args
find_args=(-type f -iname "*.mp3")

[[ "$recursive" != "true" ]] && \
    find_args=(-maxdepth 1 "${find_args[@]}")

# File list
mapfile -t files < <(
    find -L media/ "${find_args[@]}" |
    awk -F/ '{print $NF "\t" $0}' |
    sort "${sort_args[@]}" |
    cut -f2
)

[[ ${#files[@]} -gt 0 ]] || die "no mp3 files found"

# Generate items
for url in "${files[@]}"; do

    base=$(basename "$url")

    echo "Processing: $base"

    [[ "$base" =~ ^[0-9]{8} ]] || \
        die "bad filename: $base"

    y=${base:0:4}
    m=${base:4:2}
    d=${base:6:2}

    display_date=$(date -d "$y-$m-$d" +"$date_format")
    rss_date=$(date -R -d "$y-$m-$d")

    title=$(meta TITLE "$url")
    synopsis=$(meta DESCRIPTION "$url")

    [[ -n "$title" ]] || title="Untitled"

    synopsis_html=$(
        printf '%s\n' "$synopsis" |
        escape_html |
        linkify |
        sed ':a;N;$!ba;s/\n/<br>/g'
    )

    rss_url="${url_base}/${url}"
    rss_length=$(stat -c%s "$url")

    # HTML item
    item=$(<"$item_template")

    item=${item//'{{title}}'/$title}
    item=${item//'{{date}}'/$display_date}
    item=${item//'{{url}}'/$url}
    item=${item//'{{synopsis}}'/$synopsis_html}

    printf '%s\n' "$item" >> "$tmp_html_items"

    # RSS item
    rss_item=$(<"$rss_item_template")
    rss_item=${rss_item//'{{title}}'/$title}
    rss_item=${rss_item//'{{description}}'/$synopsis}
    rss_item=${rss_item//'{{link}}'/$rss_url}
    rss_item=${rss_item//'{{pubDate}}'/$rss_date}
    rss_item=${rss_item//'{{length}}'/$rss_length}
    printf '%s\n' "$rss_item" >> "$tmp_rss_items"
done

# Build final HTML
cp "$html_template" index.html
sed -i "s|{{generated}}|$generated|g" index.html
sed -i "s|{{siteurl}}|$url_base|g" index.html
sed -i "/{{items}}/r $tmp_html_items" index.html
sed -i "/{{items}}/d" index.html

# Build final RSS
cp "$rss_template" rss.xml
sed -i "s|{{generated}}|$generated|g" rss.xml
sed -i "s|{{siteurl}}|$url_base|g" rss.xml
sed -i "/{{items}}/r $tmp_rss_items" rss.xml
sed -i "/{{items}}/d" rss.xml

echo "Done"
