#!/bin/bash
# KeynoteConverter.command
# Exportiert Keynote-Präsentationen: jedes Slide als PNG, Video-Slides als Videodatei.

# ── Farben ───────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; BOLD='\033[1m'; NC='\033[0m'

log()   { echo -e "${GREEN}✓${NC}  $1"; }
info()  { echo -e "${BLUE}→${NC}  $1"; }
warn()  { echo -e "${YELLOW}⚠${NC}  $1"; }
error() { echo -e "\n${RED}✗  Fehler:${NC} $1\n" >&2; stop_spinner; echo "Drücke eine Taste..."; read -rn1; exit 1; }

SPINNER_PID=""
start_spinner() {
    local msg="$1"
    (
        local chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
        local i=0
        while true; do
            local c="${chars:$((i % ${#chars})):1}"
            printf "\r  \033[0;34m%s\033[0m  %s" "$c" "$msg"
            sleep 0.1
            (( i++ )) || true
        done
    ) &
    SPINNER_PID=$!
}
stop_spinner() {
    if [[ -n "$SPINNER_PID" ]]; then
        kill "$SPINNER_PID" 2>/dev/null
        wait "$SPINNER_PID" 2>/dev/null
        SPINNER_PID=""
        printf "\r\033[2K"
    fi
}

# ── Header ───────────────────────────────────────────────────────────────────
clear
echo ""
echo -e "  ${BOLD}Keynote → Slide Export${NC}"
echo    "  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

# ── Eingabedatei ermitteln ───────────────────────────────────────────────────
if [[ $# -ge 1 && -n "$1" ]]; then
    KEY_FILE="$1"
else
    info "Wähle eine Keynote-Datei..."
    KEY_FILE=$(osascript 2>/dev/null << 'AS'
try
    set f to choose file with prompt "Keynote-Datei auswählen (.key):"
    return POSIX path of f
on error
    return ""
end try
AS
    ) || true
fi

KEY_FILE="${KEY_FILE%$'\n'}"
KEY_FILE="${KEY_FILE% }"

[[ -z "$KEY_FILE" ]]   && error "Keine Datei ausgewählt."
[[ ! -e "$KEY_FILE" ]] && error "Datei nicht gefunden:\n  $KEY_FILE"
[[ "$KEY_FILE" != *.key ]] && error "Keine Keynote-Datei (.key) ausgewählt:\n  $KEY_FILE"

# ── Ausgabeordner anlegen ────────────────────────────────────────────────────
PRES_NAME=$(basename "$KEY_FILE" .key)
PARENT_DIR=$(dirname "$KEY_FILE")
OUTPUT_DIR="$PARENT_DIR/$PRES_NAME"

info "Präsentation:  $PRES_NAME"
info "Ausgabe:       $OUTPUT_DIR"
echo ""

mkdir -p "$OUTPUT_DIR"

# ── Keynote: Export + Movie-Analyse ─────────────────────────────────────────
KEYNOTE_WAS_RUNNING=$(osascript -e 'if application "Keynote" is running then return "yes" else return "no" end if' 2>/dev/null | tr -d '[:space:]') || KEYNOTE_WAS_RUNNING="no"

info "Öffne Datei in Keynote..."
open -a Keynote "$KEY_FILE"
sleep 5

start_spinner "Exportiere Slides..."

SCRIPT_OUT=$(osascript 2>&1 << APPLESCRIPT
set exportResult to ""

with timeout of 120 seconds
    tell application "Keynote"
        set theDoc to front document
        set totalSlides to count of slides of theDoc

        export theDoc to POSIX file "$OUTPUT_DIR" as slide images with properties {image format:PNG}

        set exportResult to "TOTAL:" & totalSlides & linefeed

        repeat with i from 1 to totalSlides
            set theSlide to slide i of theDoc
            try
                set theMovie to movie 1 of theSlide
                set movieFile to ""
                try
                    set movieFile to file name of theMovie
                end try
                set exportResult to exportResult & "MOVIE:" & i & "|" & movieFile & linefeed
            end try
        end repeat

        -- Moderationsnotizen in Textdatei schreiben
        set notesPath to "$OUTPUT_DIR/moderationsnotizen.txt"
        set notesFileRef to open for access POSIX file notesPath with write permission
        set eof of notesFileRef to 0
        set notesWritten to 0
        repeat with i from 1 to totalSlides
            set theSlide to slide i of theDoc
            set slideNotes to ""
            try
                set slideNotes to presenter notes of theSlide
            end try
            if slideNotes is not "" and slideNotes is not missing value then
                set paddedNum to i as string
                if length of paddedNum is 1 then set paddedNum to "00" & paddedNum
                if length of paddedNum is 2 then set paddedNum to "0" & paddedNum
                write "Slide " & paddedNum & ":" & linefeed to notesFileRef
                write slideNotes & linefeed & linefeed to notesFileRef
                set notesWritten to notesWritten + 1
            end if
        end repeat
        close access notesFileRef
        set exportResult to exportResult & "NOTES_WRITTEN:" & notesWritten & linefeed

        close theDoc saving no
    end tell
end timeout

return exportResult
APPLESCRIPT
) || true

if [[ "$KEYNOTE_WAS_RUNNING" != "yes" ]]; then
    osascript -e 'tell application "Keynote" to quit' 2>/dev/null || true
fi

stop_spinner

# Fehlerprüfung mit sichtbarer Ausgabe
if ! echo "$SCRIPT_OUT" | grep -q "^TOTAL:"; then
    error "Keynote-Export fehlgeschlagen.\n\nAppleScript-Ausgabe:\n$SCRIPT_OUT"
fi


TOTAL=$(echo "$SCRIPT_OUT" | grep "^TOTAL:" | sed 's/TOTAL://' | tr -d '[:space:]')
NOTES_WRITTEN=$(echo "$SCRIPT_OUT" | grep "^NOTES_WRITTEN:" | sed 's/NOTES_WRITTEN://' | tr -d '[:space:]')
log "Slides exportiert: $TOTAL"

# ── PNG-Dateien umbenennen ───────────────────────────────────────────────────
# Keynote exportiert als "<PräsName>.001.png" → umbenennen zu "001.png"
info "Benenne Dateien um..."

shopt -s nullglob
renamed=0
for f in "$OUTPUT_DIR"/*.png; do
    num=$(basename "$f" .png | grep -oE '[0-9]+$') || continue
    [[ -z "$num" ]] && continue
    padded=$(printf "%03d" "$((10#$num))")
    newpath="$OUTPUT_DIR/$padded.png"
    [[ "$f" != "$newpath" ]] && mv "$f" "$newpath"
    (( renamed++ )) || true
done
log "Dateien umbenannt: $renamed"

# ── Video-Slides verarbeiten ─────────────────────────────────────────────────
MOVIE_LINES=$(echo "$SCRIPT_OUT" | grep "^MOVIE:") || true
MOVIE_COUNT=0
[[ -n "$MOVIE_LINES" ]] && MOVIE_COUNT=$(echo "$MOVIE_LINES" | grep -c "^MOVIE:") || true

if [[ "$MOVIE_COUNT" -gt 0 ]]; then
    info "Verarbeite $MOVIE_COUNT Video-Slide(s)..."

    TEMP_BUNDLE=$(mktemp -d)

    # Inhaltsverzeichnis des Archivs einmalig einlesen (schnell)
    if [[ -d "$KEY_FILE" ]]; then
        ARCHIVE_LISTING=""
        BUNDLE_DIR="$KEY_FILE"
    else
        ARCHIVE_LISTING=$(unzip -Z1 "$KEY_FILE" 2>/dev/null | grep -iE '\.(mp4|mov|m4v|avi)$') || ARCHIVE_LISTING=""
        BUNDLE_DIR="$TEMP_BUNDLE"
    fi

    vid_num=0
    echo ""
    while IFS= read -r line; do
        [[ "$line" != MOVIE:* ]] && continue

        entry="${line#MOVIE:}"
        slide_num="${entry%%|*}"
        movie_file="${entry##*|}"

        # GIFs und Bilder überspringen – nur echte Videos
        movie_ext=$(echo "${movie_file##*.}" | tr '[:upper:]' '[:lower:]')
        case "$movie_ext" in
            gif|png|jpg|jpeg|webp) continue ;;
        esac

        (( vid_num++ )) || true
        padded=$(printf "%03d" "$((10#$slide_num))")
        movie_base="${movie_file%.*}"
        found_video=""

        if [[ -d "$KEY_FILE" ]]; then
            # Bundle-Verzeichnis: direkt suchen
            found_video=$(find "$BUNDLE_DIR" -name "${movie_base}*.${movie_ext}" 2>/dev/null | head -1) || true
        else
            # Flat Package: exakten Archiv-Pfad finden und nur diese Datei extrahieren
            archive_path=$(echo "$ARCHIVE_LISTING" | grep -F "$movie_base" | head -1)
            if [[ -n "$archive_path" ]]; then
                start_spinner "  Video $vid_num/$MOVIE_COUNT: $(basename "$archive_path")..."
                unzip -q "$KEY_FILE" "$archive_path" -d "$TEMP_BUNDLE" 2>/dev/null || true
                stop_spinner
                found_video=$(find "$TEMP_BUNDLE" -name "${movie_base}*.${movie_ext}" 2>/dev/null | head -1) || true
            fi
        fi

        if [[ -n "$found_video" ]]; then
            cp "$found_video" "$OUTPUT_DIR/$padded.${movie_ext}"
            rm -f "$OUTPUT_DIR/$padded.png"
            rm -f "$found_video"
            log "  Slide $padded → $padded.${movie_ext}"
        else
            warn "  Slide $padded: Video nicht gefunden"
        fi

    done <<< "$MOVIE_LINES"

    rm -rf "$TEMP_BUNDLE"
    echo ""
fi

# ── Zusammenfassung ───────────────────────────────────────────────────────────
shopt -s nullglob
png_files=("$OUTPUT_DIR"/*.png)
vid_files=("$OUTPUT_DIR"/*.mp4 "$OUTPUT_DIR"/*.mov "$OUTPUT_DIR"/*.m4v)
img_count=${#png_files[@]}
vid_count=${#vid_files[@]}

echo    "  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log    "Export abgeschlossen"
log    "Slides als Bild:   $img_count"
log    "Slides als Video:  $vid_count"
log    "Slides mit Notizen: $NOTES_WRITTEN → moderationsnotizen.txt"
echo ""
echo -e "  ${BOLD}$OUTPUT_DIR${NC}"
echo    "  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

open "$OUTPUT_DIR"

echo "Drücke eine Taste zum Schliessen..."
read -rn1
