#!/bin/sh -e

# A script to check for satellite updates.
# It just downloads the documents which should be updated when the software has an update.
# It's a shitty method, but it kinda works... Other than having a lot of false-positives.

_show_help() {
echo "This program will help keep your satellites fresh and up to date.
Usage: $0 <[\$dir_satellites] [\$_dir_fresh]|ignore <diff> <ignorediff>>

\$dir_satellites = The directory where all the satellites are you want to update.
\$_dir_fresh = The directory that will be used to keep all the files for checking.
ignore = Use this option to generate an ignorediff.
diff = A diff file. Generated without -u or any other fancy options.
ignorediff = A file containing the differences to be ignored (this file will be appended to).

The variables (starting with \$) can also be set from a configuration file."
}

get_variable() {
    printf "
        download() { :; }
        extract() { :; }
        getfile() { :; }
        extrafile() { :; }
        dlextract() { :; }
        dlfile() { :; }
        header_end() { echo \$$1; exit; }
        . %s
    " $2 | sh
}

download() {
    $(echo "$cmd_download" | sed -e 's@{dst}@'"$2"'@g' -e 's@{src}@'"$1"'@g') 2> /dev/null
}

diff_extractlines() {
    # Extract all the line numbers from a diff.

    stage=0
    for line in $(echo "$1" | awk '{print $1}'); do
        if [ "$stage" = 0 ]; then
            if [ "$line" != ">" -a "$line" != "<" ]; then
                echo "$line"
                stage=1
            fi
        elif [ "$stage" = 1 ]; then
            if [ "$line" != ">" -a "$line" != "<" ]; then
                if [ "$line" = "---" ]; then
                    stage=0
                else
                    echo "$line"
                fi
            fi
        fi
    done
}

apply_ignorediff() {
    # Filter a diff, only return the differences that shouldn't be ignored.
    # TODO: This function is slow, due to the usage of awk on every line. A solution for this problem would be great.

    stage=0
    ignore=0
    echo "$1" | while read line; do
        first="$(echo "$line" | awk '{print $1}')"
        if [ "$stage" = 0 ]; then
            if [ "$first" != ">" -a "$first" != "<" ]; then
                stage=1
                ignore=0
                if grep -e "^$line\$" "$2" > /dev/null; then
                    ignore=1
                fi
            fi
        elif [ "$stage" = 1 ]; then
            if [ "$first" != ">" -a "$first" != "<" ]; then
                if [ "$line" = "---" ]; then
                    stage=0
                else
                    ignore=0
                    if grep -e "^$line\$" "$2" > /dev/null; then
                        ingore=1
                    fi
                fi
            fi
        fi

        if [ "$ignore" = 0 ]; then
            echo "$line"
        fi
    done
}

# Do something completely different when this option is provided.
if [ "$1" = "ignore" ]; then
    if [ $# -lt 3 ]; then
        _show_help
        exit 1
    fi

    diff_extractlines "$(cat "$2")" >> "$3"

    # Don't do anything else
    exit
fi

# Load the config
cmd_download="curl -L -o {dst} {src}"  # Command to execute to download files
[ -f /etc/astronaut.conf ] && . /etc/astronaut.conf
[ -f "$HOME/.astronaut.conf" ] && . "$HOME/.astronaut.conf"

# Override config with command-line parameters.
[ "$1" ] && dir_satellites="$1"
[ "$2" ] && _dir_fresh="$2"

if [ ! "$dir_satellites" -o ! "$_dir_fresh" ]; then
    _show_help
    exit 1
fi

mkdir -p "$_dir_fresh"

for sat in "$dir_satellites"/*.sat; do
    update_url="$(get_variable update_url "$sat")"
    name="$(basename "$sat" .sat)"

    if [ "$update_url" ]; then
        printf "Checking: $name..."
        cols="$(expr $(tput cols) - $(printf "Checking: $name..." | wc -c))"

        download "$update_url" "$_dir_fresh/$name.fresh"

        if [ -f "$_dir_fresh/$name" ]; then
            check="$(diff "$_dir_fresh/$name" "$_dir_fresh/$name.fresh" || true)"

            if [ -f "$_dir_fresh/$name.ignorediff" ]; then
                check="$(apply_ignorediff "$check" "$_dir_fresh/$name.ignorediff")"
            fi

            if [ "$check" ]; then
                printf "%${cols}s\n" "Update detected"
                echo "$check" >> "$_dir_fresh/$name-$(date +%Y%m%d%H%M%S).diff"
            else
                printf "\n"
            fi
        else
            printf "%${cols}s\n" "First update check, creating new file"
            download "$update_url" "$_dir_fresh/$name.checkfresh"
            check="$(diff "$_dir_fresh/$name.fresh" "$_dir_fresh/$name.checkfresh" || true)"

            if [ "$check" ]; then
                echo "$(diff_extractlines "$check")" >> "$_dir_fresh/$name.ignorediff"
                echo "> Created ignorediff"
            fi

            rm "$_dir_fresh/$name.checkfresh"
        fi

        mv "$_dir_fresh/$name.fresh" "$_dir_fresh/$name"
    fi
done