#!/usr/bin/env bash
#
# Bisect parsing a file at various line cut-off points to see which line causes the parse to differ from emacs.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

cd "$DIR/../"
REALPATH=$(command -v uu-realpath || command -v realpath)

############## Setup #########################

function cleanup {
    for f in "${folders[@]}"; do
        log "Deleting $f"
        rm -rf "$f"
    done
}
folders=()
for sig in EXIT INT QUIT HUP TERM; do
  trap "set +e; cleanup" "$sig"
done

function die {
    local status_code="$1"
    shift
    (>&2 echo "${@}")
    exit "$status_code"
}

function log {
    (>&2 echo "${@}")
}

############## Program #########################

function main {
    log "Is is recommended that the output of \`mktemp -d -t 'compare_bisect.XXXXXXXX'\` is inside a tmpfs filesystem since this script will make many writes to these folders."

    local target_full_path=$($REALPATH "$1")
    SOURCE_FOLDER=$(dirname "$target_full_path")
    TARGET_DOCUMENT=$(basename "$target_full_path")


    local good=0
    local bad=$(wc -l "$SOURCE_FOLDER/$TARGET_DOCUMENT" | awk '{print $1}')

    set +e
    run_parse "$bad" &> /dev/null
    local status=$?
    set -e
    if [ $status -eq 0 ]; then
        log "Entire file passes."
        exit 0
    fi

    while [[ "$((bad - good))" -gt 1 ]]; do
        local next_line=$((((bad - good) / 2) + good))
        log "Testing line $next_line"
        set +e
        run_parse "$next_line" &> /dev/null
        local status=$?
        set -e
        if [ $status -eq 0 ]; then
            good="$next_line"
            log "Line $next_line good"
        else
            bad="$next_line"
            log "Line $next_line bad"
        fi
    done
    echo "Bad line: $bad"
}

function setup_temp_dir {
    local temp_dir=$(mktemp -d -t 'compare_bisect.XXXXXXXX')
    cp -r "$SOURCE_FOLDER/"* "$temp_dir/"
    echo "$temp_dir"
}

function run_parse {
    local lines="$1"
    local temp_dir=$(setup_temp_dir)
    folders+=("$temp_dir")
    cat "$SOURCE_FOLDER/$TARGET_DOCUMENT" | head -n "$lines" > "$temp_dir/$TARGET_DOCUMENT"
    "${DIR}/run_docker_compare.bash" "$temp_dir/$TARGET_DOCUMENT"
    local status=$?
    rm -rf "$temp_dir"
    # TODO: Remove temp_dir from folders
    return "$status"
}

main "${@}"