#!/usr/bin/env bash
set -euo pipefail

POSTGRESQL_SHARE_DIR="$(pg_config --sharedir)"
POSTGIS_CONTROL="${POSTGRESQL_SHARE_DIR}/extension/postgis.control"
POSTGIS_VERSION_MAJOR="$(perl -ne "print if s/^default_version = '(\d).*$/\$1/" "${POSTGIS_CONTROL}")"

export PGTZ="PST8PDT"
export PGDATESTYLE="Postgres, MDY"

export PGOPTIONS="-c session_preload_libraries=${POSTGIS_LIBRARY}"

TEST_ABS_SRCDIR="${PWD}/mobilitydb/test"

DIFFS=()

fail() {
    echo >&2 "$@"
    exit 1
}

run_compare() {
    local test_name="$1"
    local test_file="$2"

    [[ -n $test_name ]] || fail "argument 'test_name' must be provided"
    [[ -n $test_file ]] || fail "argument 'test_file' must be provided"

    printf "test %-28s ... " "${test_name}"
    # execute the test
    # remove unicode byte order mark from queries
    # only npoint seems to have this issue
    sed '1s/^\xEF\xBB\xBF//' "${test_file}" | psql -e --set ON_ERROR_STOP=0 &>"${AUTOPKGTEST_TMP}/${test_name}.out"
    local test_file_dir
    test_file_dir="$(dirname "${test_file}")"
    test_file_dir="${test_file_dir%/queries}"

    local test_file_name
    test_file_name="$(basename "${test_file}" .test.sql)"
    if ! diff -urdN "${AUTOPKGTEST_TMP}/${test_name}.out" "${test_file_dir}/expected/${test_file_name}.test.out" >"${AUTOPKGTEST_TMP}/${test_name}.diff"; then
        DIFFS+=("${AUTOPKGTEST_TMP}/${test_name}.diff")
        printf "FAILED\n"
    else
        printf "ok    \n"
    fi
}

run_passfail() {
    local test_name="$1"
    local test_file="$2"

    [[ -n $test_name ]] || fail "argument 'test_name' must be provided"
    [[ -n $test_file ]] || fail "argument 'test_file' must be provided"

    if [[ $test_file == *.xz ]]; then
        xzcat "${test_file}" | sed '1s/^\xEF\xBB\xBF//' | psql -e --set ON_ERROR_STOP=0 &>"${AUTOPKGTEST_TMP}/${test_name}.out"
    else
        sed '1s/^\xEF\xBB\xBF//' | psql -e --set ON_ERROR_STOP=0 &>"${AUTOPKGTEST_TMP}/${test_name}.out"
    fi
}

general() {
    run_passfail load_tables "${TEST_ABS_SRCDIR}/general/data/load.sql.xz"

    local test_file
    for test_file in "${TEST_ABS_SRCDIR}"/general/queries/*.sql; do
        local test_name
        test_name="$(basename "$test_file" .test.sql)"
        if [[ $test_name =~ _pg([0-9]+) ]]; then
            if [[ $PGVERSION -lt ${BASH_REMATCH[1]} ]]; then
                printf "test %-28s ... %s" "${test_name}" "skipped"
                continue
            fi
        fi

        run_compare "$test_name" "$test_file"
    done
}

point() {
    run_passfail load_point_tables "${TEST_ABS_SRCDIR}/point/data/load_point.sql.xz"

    local test_file
    for test_file in "${TEST_ABS_SRCDIR}"/point/queries/*.sql; do
        local test_name
        test_name="$(basename "$test_file" .test.sql)"
        if [[ $test_name =~ _pg([0-9]+) ]]; then
            if [[ $PGVERSION -lt ${BASH_REMATCH[1]} ]]; then
                printf "test %-28s ... %s" "${test_name}" "skipped"
                continue
            fi
        fi

        if [[ $test_name =~ _pgis([0-9]+) ]]; then
            if [[ $POSTGIS_VERSION_MAJOR -lt ${BASH_REMATCH[1]} ]]; then
                printf "test %-28s ... %s" "${test_name}" "skipped"
                continue
            fi
        fi

        run_compare "$test_name" "$test_file"
    done
}

npoint() {
    run_passfail load_npoint_tables "${TEST_ABS_SRCDIR}/npoint/data/load_npoint.sql.xz"

    local test_file
    for test_file in "${TEST_ABS_SRCDIR}"/npoint/queries/*.sql; do
        local test_name
        test_name="$(basename "$test_file" .test.sql)"
        if [[ $test_name =~ _pg([0-9]+) ]]; then
            if [[ $PGVERSION -lt ${BASH_REMATCH[1]} ]]; then
                printf "test %-28s ... %s" "${test_name}" "skipped"
                continue
            fi
        fi

        run_compare "$test_name" "$test_file"
    done
}

# create PostGIS and MobilityDB extensions
psql -e --set ON_ERROR_STOP=0 &>"${AUTOPKGTEST_TMP}/create_ext.log" <<ESQL
CREATE EXTENSION mobilitydb CASCADE;
SELECT postgis_full_version();
SELECT mobilitydb_full_version();
ESQL

general
point
npoint

if ((${#DIFFS[@]})); then
    echo "${#DIFFS[@]} tests failed ... "
    for d in "${DIFFS[@]}"; do
        head -n 100 "${d}"
    done
    exit 1
fi
