#!/usr/bin/env bash

# Optimizes everything the script can find in a folder,
# meaning it will compress files as much as possible,
# without losing any data (verification will be done
# in order to verify that no data has been done)
# (executable)

# TODO Run in parallel
# TODO Lots of dupplicated code there

dir=${1:-$PWD}
total=$(mktemp)
echo -n 0 > $total

function showtotal {
    echo "Total saved: $(cat "$total") bytes"
    rm $total
    exit
}

trap showtotal SIGTERM SIGINT SIGFPE

function doReplace { # candidate original
    mv "$c" "$o"
    saved=$(($os - $cs))
    perc=$((100 * $saved / $os))
    echo "→ $os ⇒ $cs (saved $saved bytes, or ${perc}%)"
    newtotal=$(($(cat $total) + $saved))
    echo -n $newtotal > $total
}

function replace { # candidate original
    c="$1"
    o="$2"

    # File verifications
    if [ ! -f "$o" ]; then
        echo "→ Original is inexistant, skipping!"
        return
    fi
    if [ ! -f "$c" ]; then
        echo "→ Candidate is inexistant, skipping!"
        return
    fi

    # Size verifications
    cs=$(wc -c "$c" | cut -d' ' -f1)
    os=$(wc -c "$o" | cut -d' ' -f1)
    if [ $cs -le 0 ]; then
        echo "→ Candidate is empty, skipping!"
        rm "$c"
        return
    fi
    if [ $cs -eq $os ]; then
        echo "→ Candidate weight the same, skipping."
        rm "$c"
        return
    fi
    if [ $cs -gt $os ]; then
        echo "→ Candidate is larger, skipping."
        rm "$c"
        return
    fi

    doReplace "$c" "$o"
}

function replaceImg { # candidate original
    # With bitmap verification

    c="$1"
    o="$2"

    # File verifications
    if [ ! -f "$o" ]; then
        echo "→ Original is inexistant, skipping!"
        return
    fi
    if [ ! -f "$c" ]; then
        echo "→ Candidate is inexistant, skipping!"
        return
    fi

    # Size verifications
    cs=$(wc -c "$c" | cut -d' ' -f1)
    os=$(wc -c "$o" | cut -d' ' -f1)
    if [ $cs -le 0 ]; then
        echo "→ Candidate is empty, skipping!"
        rm "$c"
        return
    fi
    if [ $cs -eq $os ]; then
        echo "→ Candidate weight the same, skipping."
        rm "$c"
        return
    fi
    if [ $cs -gt $os ]; then
        echo "→ Candidate is larger, skipping."
        rm "$c"
        return
    fi

    # Bitmap verification
    ppmc="$(mktemp --suffix .ppm)"
    ppmo="$(mktemp --suffix .ppm)"
    convert "$c" "$ppmc"
    convert "$o" "$ppmo"

    if cmp --silent "$ppmo" "$ppmc"; then
        doReplace "$c" "$o"
    else
        echo "→ Candidate don't have the same bit map as original, skipping!"
    fi
    rm -f "$ppmc" "$ppmo" "$c"

}

# JPEG (requires jpegtran)
while read image
do
    if [ -z "$image" ]; then continue; fi
    echo Processing $image

    prog=$(mktemp --suffix .jpg)
    jpegtran -copy all -progressive "$image" > "$prog"
    echo "→ Progressive done"
    progs=$(wc -c "$prog" | cut -d' ' -f1)
    replace "$prog" "$image"


done <<< "$(find "$dir" -type f -iregex ".+.jpe?g$")"

# PNG (requires optipng)
while read image
do
    if [ -z "$image" ]; then continue; fi
    echo Processing $image

    temp=$(mktemp --suffix .png)
    cp "$image" "$temp"
    optipng -quiet "$temp"
    echo "→ Optimize done"

    replace "$temp" "$image"

done <<< "$(find "$dir" -type f -iname "*.png")"

# # SVG (requires scour)
# while read image
# do
#     if [ -z "$image" ]; then continue; fi
#     echo Processing $image
#
#     temp=$(mktemp --suffix .svg)
#     scour --quiet "$image" "$temp" --no-line-breaks
#     echo "→ Optimize done"
#
#     replaceImg "$temp" "$image"
#
# done <<< "$(find "$dir" -type f -iname "*.svg")"

# NOTE Explicitely disabled since:
# - I only have ~50 MiB of SVG in TOTAL
# - Most conversions are not image losseless
# - Even when they are losseless, they are mostly worthless
# - I might want to keep editor data and/or ids for some of them
# So rather use scour explicitely when needed

cleandev

showtotal