if [ -z "${__KESL_INCLUSE_SH_INCLUDE_GUARD__:-}" ]; then
readonly __KESL_INCLUSE_SH_INCLUDE_GUARD__=1

if [ -z "${KESL_INCLUDE_SH_STANDALONE:-}" ]; then
    : "${KESL_INCLUDE_SH_PATH:?The 'KESL_INCLUDE_SH_PATH' variable must be set and not null}"
fi

__GetKeslIncludedSpecs__()
{
    local _module="${1%.inc}"
    : "${_module:?Module name must be specified}"

    shift

    eval "${1#@}=\${_module}"
    
    local _hash=$(printf '%s' "${_module}" | md5sum | { IFS=' ' read -r hashValue fileName; printf '%s' "${hashValue}"; })
    eval "${2#@}=__KESL_INCLUDE_SH_MODULE_${_hash}__"
}

StandaloneSh()
{
    : "${KESL_INCLUDE_SH_STANDALONE:?KESL_INCLUDE_SH_STANDALONE variable must be set and not null}"

    local incModuleName=''
    local incGuardVarName=''
    __GetKeslIncludedSpecs__ "${1}" @incModuleName @incGuardVarName

    eval "${incGuardVarName}=1"
}

IncludeSh()
{
    local incModuleName=''
    local incGuardVarName=''
    __GetKeslIncludedSpecs__ "${1}" @incModuleName @incGuardVarName

    if ! eval "test -z \"\${${incGuardVarName}:-}\""; then
        return
    fi

    if [ ! -z "${KESL_INCLUDE_SH_STANDALONE:-}" ]; then
        eval : "\${${incGuardVarName}:?Module ${incModuleName} source code must be subtituted and marked as standalone by the StandaloneSh() function.}"
        return
    fi

    : "${KESL_INCLUDE_SH_PATH:?KESL_INCLUDE_SH_PATH variable must be set and not null}"

    local path="${KESL_INCLUDE_SH_PATH%%:*}"
    local rest="${KESL_INCLUDE_SH_PATH#:*}"

    while :; do
        if [ "${path#/}" = "${path}" ]; then
            echo "ERROR: sh-include path must be an absolute path: '${path}'" 1>&2
            exit 1
        fi

        local moduleFilePath="${path}/${incModuleName}.inc"
        if [ -f "${moduleFilePath}" ]; then
            eval "${incGuardVarName}=1"
            . "${moduleFilePath}" || return $?
            break
        fi

        path="${rest%%:*}"
        rest="${rest#:*}"
        if [ "${path}" = "${rest}" ]; then
            echo "ERROR: module '${incModuleName}' is not found" 1>&2
            exit 1
        fi
    done
}

fi
