#!/bin/bash
# AVL-MXe FFmpeg Simple Concatenator + Automated Chapter Generator
# Concept and Testing by Glen MacArthur, coded by Google Gemini 3

# 1. Sort incoming arguments
IFS=$'\n' FILES=($(sort <<<"$*"))
unset IFS

if [ ${#FILES[@]} -lt 2 ]; then
    yad --error --text="Please select at least two files." --width=320 --center
    exit 1
fi

# 2. Preview Dialog
PREVIEW_LIST=$(for f in "${FILES[@]}"; do basename "$f"; done)

yad --text-info \
    --title="FFmpeg Media File Joiner" \
    --image="/usr/local/share/icons/custom/ffmpeg-app.png" \
    --window-icon="/usr/local/share/icons/custom/ffmpeg.png" \
    --width=500 --height=350 --center \
    --text="<b>Displaying Assembly Order:</b>\nFiles must be prefix-numbered for desired order!" \
    --button="New Audio (AC3-only)":10 \
    --button="Stream Copy (Other Formats)":12 \
    --button="Cancel":1 <<< "$PREVIEW_LIST"

ACTION=$?
[[ $ACTION -eq 1 || $ACTION -eq 252 ]] && exit 1

# 3. Prepare manifest & Track Chapter Timestamps
LIST_FILE=$(mktemp)
META_FILE=$(mktemp)

# Initialize strict FFmpeg metadata header
echo ";FFMETADATA1" > "$META_FILE"

CURRENT_TIME_MS=0
CHAPTER_TIMES_TXT=""

for f in "${FILES[@]}"; do
    # Format entry for the concat list file
    printf "file '%s'\n" "$(echo "$f" | sed "s/'/'\\\\''/g")" >> "$LIST_FILE"
    
    # Get duration of current file in seconds using ffprobe
    DURATION_SEC=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$f")
    
    # Convert running clock to a clean DVD-authoring timestamp string (HH:MM:SS.mmm)
    C_HOURS=$((CURRENT_TIME_MS / 3600000))
    C_MINS=$(((CURRENT_TIME_MS % 3600000) / 60000))
    C_SECS=$(((CURRENT_TIME_MS % 60000) / 1000))
    C_MS=$((CURRENT_TIME_MS % 1000))
    TIMESTAMP_STR=$(printf "%02d:%02d:%02d.%03d" $C_HOURS $C_MINS $C_SECS $C_MS)
    
    # Append to our DVD authoring list (skip adding a chapter point at exactly 00:00:00 if needed, but usually kept)
    CHAPTER_TIMES_TXT+="${TIMESTAMP_STR},"

    # Safely convert duration to milliseconds using bc for floating-point math
    DURATION_MS=$(echo "$DURATION_SEC * 1000" | bc | cut -d'.' -f1)
    [[ -z "$DURATION_MS" ]] && DURATION_MS=0
    
    START_TIME=$CURRENT_TIME_MS
    END_TIME=$((CURRENT_TIME_MS + DURATION_MS))
    CHAPTER_NAME=$(basename "${f%.*}")
    
    # Append clean chapter markers matching standard structural spec
    {
        echo "[CHAPTER]"
        echo "TIMEBASE=1/1000"
        echo "START=$START_TIME"
        echo "END=$END_TIME"
        echo "title=$CHAPTER_NAME"
    } >> "$META_FILE"
    
    # Advance the running clock for the next file
    CURRENT_TIME_MS=$END_TIME
done

# Strip trailing comma from the timestamp string
CHAPTER_TIMES_TXT=$(echo "$CHAPTER_TIMES_TXT" | sed 's/,$//')

# 4. Define Flags & Output
EXTENSION="${FILES[0]##*.}"
OUTPUT_FILE="${FILES[0]%.*}_JOINED_$(date +%H%M%S).${EXTENSION}"
CHAPTERS_FILE="${OUTPUT_FILE%.*}.chapters.txt"

# DVD-Specific Muxing (The "Hardening" layer)
if [[ "${EXTENSION,,}" =~ ^(mpg|mpeg|vob)$ ]]; then
    CONTAINER_FLAGS="-f dvd -muxrate 10080k -maxrate 8500k -bufsize 1835k -packet_size 2048"
else
    CONTAINER_FLAGS=""
fi

# Handle Actions
if [ $ACTION -eq 12 ]; then
    # Stream Copy (Both Video and Audio)
    FFMPEG_OPTS="-c:v copy -c:a copy"
else
    # Pro Audio (Apply Loudnorm, must re-encode AC3)
    LOUDNORM="loudnorm=I=-16:LRA=11:TP=-1.5"
    FFMPEG_OPTS="-c:v copy -af $LOUDNORM -c:a ac3 -b:a 448k -ar 48000 -ac 2"
fi

# 5. Execution
terminology -T="Assembling Files" -e bash -c "echo 'Assembling Files with Chapters...'; \
ffmpeg -f concat -safe 0 -i '$LIST_FILE' -i '$META_FILE' \
-fflags +genpts -avoid_negative_ts make_zero \
$FFMPEG_OPTS $CONTAINER_FLAGS -map_metadata 1 -map_chapters 1 '$OUTPUT_FILE'; \
echo -e '\nDone! Output: $(basename \"$OUTPUT_FILE\")'; read -n 1"

# Save out the companion chapter text file for DVDauthor / GUI tools
echo "$CHAPTER_TIMES_TXT" > "$CHAPTERS_FILE"

# Cleanup temporary tracking manifests
rm -f "$LIST_FILE" "$META_FILE"