#!/bin/bash

set -pu

function call_set_config_file_create_false {
    {{{ set_config_file("$1", "Compression", "no", False) | indent(4) }}}
}


function call_set_config_file {
    {{{ set_config_file("$1", "Compression", "no", True) | indent(4) }}}
}

function call_set_config_file_rsyslog {
    {{{ set_config_file(path="$1",
            parameter="\$DefaultNetstreamDriver", value="gtls",
            create=true, separator=" ", separator_regex=" ") }}}
}

is_old_bats=0

setup() {
    if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then
        BATS_TEST_TMPDIR="$(mktemp -d)"  # 1.4.0
        # shellcheck disable=SC2034
        BATS_TEARDOWN_STARTED=  # 1.3.0
        is_old_bats=1
    else
        is_old_bats=0
    fi
    pushd "${BATS_TEST_TMPDIR}" || exit 1
    tmp_file=test.conf
    touch "$tmp_file"
}

teardown() {
    if (( is_old_bats )); then
        if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then
            >&2 echo "INTERNAL ERROR"
            exit 3
        fi
        local tmppath xpwd
        tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")"
        if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then
            >&2 echo "INTERNAL ERROR"
            exit 3
        fi
        xpwd="$(readlink -f -- .)"
        if [[ "${tmppath}" != "${xpwd}" ]]; then
            >&2 echo "INTERNAL ERROR"
            exit 3
        fi
        popd || exit 1
        rm -rf -- "${tmppath}"
        BATS_TEST_TMPDIR=""
    fi
}

@test "set_config_file - Basic value remediation" {
    printf "%s\n" "Compression yes" > "$tmp_file"
    expected_output="Compression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - No remediation happened" {
    printf "%s\n" "Compression no" > "$tmp_file"
    expected_output="Compression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Multiline file remediation" {
    printf "%s\n" "Protocol 2" "Compression yes" "Port 22" > "$tmp_file"
    expected_output="Protocol 2\nPort 22\nCompression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - No remediation on commented line" {
    printf "%s\n" "Protocol 2" "# Compression yes" "Port 22" > "$tmp_file"
    expected_output="Protocol 2\n# Compression yes\nPort 22\nCompression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Create if missing" {
    printf "%s\n" "Protocol 2" "Port 22" > "$tmp_file"
    expected_output="Protocol 2\nPort 22\nCompression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Create file if doesn't exist" {
    rm "$tmp_file"
    expected_output="Compression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Do not create if missing" {
    rm "$tmp_file"

    run call_set_config_file_create_false "$tmp_file"

    [ "$status" -eq 1 ]
    [[ "$output" =~ "Path '$tmp_file' wasn't found" ]]
}


@test "set_config_file - Case insensitive remediation" {
    printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file"
    expected_output="Protocol 2\nPort 22\nCompression no\n"

    call_set_config_file "$tmp_file"

    run diff "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Case sensitive remediation" {
    printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file"
    expected_output="Protocol 2\nCOMPRESSION YES\nPort 22\nCompression no\n"

    {{{ set_config_file("$tmp_file", "Compression", "no", True, "", "", False) | indent(4) }}}

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Basic Bash remediation" {
    printf "%s\n" "something=foo" > "$tmp_file"
    expected_output="something='va lue'\n"

    {{{ bash_shell_file_set("$tmp_file", "something", "va lue") | indent(4) }}}

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Variable remediation - preserve dollar and use double quotes" {
    printf "%s\n" "something=bar" > "$tmp_file"
    expected_output='something="$value"'"\n"

    {{{ bash_shell_file_set("$tmp_file", "something", '$value') | indent(4) }}}

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Basic Bash remediation - don't quote" {
    printf "%s\n" "something=foo" > "$tmp_file"
    expected_output="something=va lue\n"

    {{{ bash_shell_file_set("$tmp_file", "something", "va lue", no_quotes=true) | indent(4) }}}

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - Variable remediation - don't quote" {
    printf "%s\n" "something=bar" > "$tmp_file"
    expected_output='something=$value'"\n"

    {{{ bash_shell_file_set("$tmp_file", "something", '$value', no_quotes=true) | indent(4) }}}

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}

@test "set_config_file - handle escaped dollar" {
    printf "%s\n" '$DefaultNetstreamDriver bad' > "$tmp_file"
    expected_output='$DefaultNetstreamDriver gtls'"\n"

    call_set_config_file_rsyslog "$tmp_file"

    run diff -U2 "$tmp_file" <(printf "$expected_output")
    [ "$status" -eq 0 ]
}
