argument_testing() {
    local -r short_arg="${1}"
    local -r long_arg="${2}"
    local -r flag_name="${3}"
    local -r expected_value="${4}"
    local -r cmd_arg="${5:-""}"
    local init_value=0

    flags=("FLAG_AUTOTYPE" "FLAG_COPY" "FLAG_FILEISUSER" "FLAG_HELP" "FLAG_SQUASH" "FLAG_TYPE" "FLAG_HOTKEYS_SUPPORTED")

    [ ${expected_value} -eq 0 ] && init_value=1

    for flag in "${flags[@]}"; do
        declare "${flag}"=${init_value}
    done
    CMD_COPY="wl-copy"
    CMD_TYPE="wtype -"
    EXPECTED_CMD_COPY="${CMD_COPY}"
    EXPECTED_CMD_TYPE="${CMD_TYPE}"
    [[ "${flag_name}" == "FLAG_COPY" ]] && EXPECTED_CMD_COPY="${cmd_arg:-"wl-copy"}"
    [[ "${flag_name}" == "FLAG_TYPE" ]] && EXPECTED_CMD_TYPE="${cmd_arg:-"wtype -"}"


    parse_arguments "-${short_arg}${cmd_arg}"
    assert_equals ${expected_value} ${!flag_name} "args: ${flag_name} was not set"

    declare "${flag_name}"=${init_value}
    arg="${long_arg}"
    [ -n "${cmd_arg}" ] && arg="${long_arg}=${cmd_arg}"
    parse_arguments "--${arg}"
    assert_equals ${expected_value} ${!flag_name} "args: ${flag_name} was not set"


    for flag in "${flags[@]}"; do
        value=${init_value}
        if [[ "${flag_name}" == "${flag}" ]]; then
            value=${expected_value}
        fi
        assert_equals ${value} ${!flag} "args: ${flag} is not ${value}"
    done
    assert_equals "${EXPECTED_CMD_COPY}" "${CMD_COPY}" "args: CMD_COPY is not \"${EXPECTED_CMD_COPY}\""
    assert_equals "${EXPECTED_CMD_TYPE}" "${CMD_TYPE}" "args: CMD_TYPE is not \"${EXPECTED_CMD_TYPE}\""
}

test_args_autotype() {
    argument_testing "a" "autotype" "FLAG_AUTOTYPE" 1
}

test_args_copy() {
    argument_testing "c" "copy" "FLAG_COPY" 1
    argument_testing "c" "copy" "FLAG_COPY" 1 "new-copy-cmd"
}

test_args_fileisuser() {
    argument_testing "f" "fileisuser" "FLAG_FILEISUSER" 1
}

test_args_help() {
    argument_testing "h" "help" "FLAG_HELP" 1
}

test_args_insensitive() {
    argument_testing "i" "insensitive" "FLAG_CASE_INSENSITIVE" 1
}

test_args_squash() {
    argument_testing "s" "squash" "FLAG_SQUASH" 1
}

test_args_type() {
    argument_testing "t" "type" "FLAG_TYPE" 1
    argument_testing "t" "type" "FLAG_TYPE" 1 "new-type-cmd"
}

test_args_nohotkey() {
    argument_testing "k" "nohotkey" "FLAG_HOTKEYS_SUPPORTED" 0
}

test_args_unknown() {
    options_text="$(getopt --options "a" -n "wofi-pass" -- "-x" 2>&1 | head -1)"
    options_text="${options_text%--*}"

    longoptions_text="$(getopt --options "a" --longoptions "aa" -n "wofi-pass" -- "--not-exist" 2>&1 | head -1)"
    longoptions_text="${longoptions_text%--*}"

    error_out="$(parse_arguments --not-exist 2>&1)"
    assert_matches "${longoptions_text}.*" "${error_out}" "args: parsed not defined parameter"
    error_out="$(parse_arguments -f --type --not-exist 2>&1)"
    assert_matches "${longoptions_text}.*" "${error_out}" "args: parsed not defined parameter"
    error_out="$(parse_arguments -a --not-exist -t 2>&1)"
    assert_matches "${longoptions_text}.*" "${error_out}" "args: parsed not defined parameter"

    error_out="$(parse_arguments -x 2>&1)"
    assert_matches "${options_text}.*" "${error_out}" "args: parsed not defined parameter"
    error_out="$(parse_arguments -f --type -x 2>&1)"
    assert_matches "${options_text}.*" "${error_out}" "args: parsed not defined parameter"
    error_out="$(parse_arguments -a -x -t 2>&1)"
    assert_matches "${options_text}.*" "${error_out}" "args: parsed not defined parameter"
}

setup_suite() {
    WOFI_PASS_TESTING="1"
    source ../wofi-pass
}
