#!/bin/bash

EXCLUDED_ROOT_DIRECTORIES=( "3rdparty" "apps" )
PREFERRED_CLANG_FORMAT_VERSION="13"

is_in_excluded_directory () {
    local file directory

    file="$1"
    for directory in "${EXCLUDED_ROOT_DIRECTORIES[@]}"; do
        [[ "${file}" == ${directory}* ]] && return 0
    done
    return 1
}

format_c_cpp () {
    local clang_format_binary file

    if [[ -n "${PREFERRED_CLANG_FORMAT_VERSION}" ]] && \
       command -v "clang-format-${PREFERRED_CLANG_FORMAT_VERSION}" >/dev/null 2>&1; then
      clang_format_binary="clang-format-${PREFERRED_CLANG_FORMAT_VERSION}"
    else
      clang_format_binary="clang-format"
    fi

    # Only check staged files (relevant for the current commit) that
    # were added, copied, modified or renamed.
    for file in $(git diff --cached --name-only --diff-filter=ACMR); do
        ! is_in_excluded_directory "${file}" || continue
        [[ "${file}" =~ \.(c|cpp|cxx|m|h|hpp|hxx)$ ]] || continue
        grep -vr $'\r' "${file}" >/dev/null || { echo "${file} must not contain carriage return as line endings."; return 1; }
        file --mime "${file}" | grep "charset=us-ascii" >/dev/null || { echo "${file} must be encoded as ASCII text."; return 1; }
        "${clang_format_binary}" -i -verbose -style=file "${file}" && \
        git add "${file}" || exit 1
    done
    return 0
}

format_cmake () {
    local cmake_format file

    cmake_format="$(./.setup_cmakeformat.sh)"
    # Only check staged files (relevant for the current commit) that
    # were added, copied, modified or renamed.
    for file in $(git diff --cached --name-only --diff-filter=ACMR); do
        ! is_in_excluded_directory "${file}" || continue
        [[ "${file}" =~ (^|/)CMakeLists.txt$ || "${file}" =~ \.cmake$ ]] || continue
        grep -vr $'\r' "${file}" >/dev/null || { echo "${file} must not contain carriage return as line endings."; return 1; }
        file --mime "${file}" | grep "charset=us-ascii" >/dev/null || { echo "${file} must be encoded as ASCII text."; return 1; }
        # `cmake-format` reads the configuration file `.cmake-format.py` in the top level directory
        echo "Formatting ${file}"
        "${cmake_format}" -i "${file}" && \
        git add "${file}" || exit 1
    done
    return 0
}

main () {
    format_c_cpp && \
    format_cmake
}

main "$@"
