#!/bin/bash

# Copyright (c)      2020 STE||AR GROUP
#
# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

function check_failure {
    string_to_grep=$1
    tmp_module=$2
    cmakelist=$3
    grep -Fq "$string_to_grep" $cmakelist
    if [[ $? -eq 1 ]]; then
        echo "Missing ${string_to_grep} in libs/${tmp_module}/CMakeLists.txt"
    fi
}

# Check the dependencies of the module listed in its CMakeLists.txt
function check_module_dependencies() {
    tmp_module=$1
    tmp_module_name=$(basename $tmp_module)
    tmp_group_list=$3

    # Find the dependencies through the includes and remove pika/pika_* like
    includes=($(grep -Erho 'pika/modules/[_a-z]*\.hpp\>' --include=*.{hpp,cpp} include src 2>/dev/null | sort | uniq | grep -v pika/pika))

    # Check if the dependency is inside the CMakeLists.txt
    for include in "${includes[@]}"; do
        # Isolate the name of the module from the include
        module_deps=$(basename $include | cut -d'.' -f1)
        # Check if the name is not the current module and check if it is
        # contained in the current module group
        if [[ ! "$module_deps" == "$tmp_module_name" ]]; then
            for group_module in ${tmp_group_list}; do
                if [[ "$module_deps" == "$group_module" ]]; then
                    check_failure "pika_${module_deps}" $tmp_module CMakeLists.txt
                    break
                fi
            done
        fi
    done
}

function check_cmakelists_files() {
    tmp_module=$1
    tmp_dir=$2
    if [ -d $tmp_dir ]; then
        pushd $tmp_dir >/dev/null

        # Silence the .cpp not found errors in include dir and inversely
        module_files=($(ls **/*.{hpp,cpp} 2>/dev/null))
        # Check the presence of the header in the CMakeLists.txt of the module
        for header in "${module_files[@]}"; do
            check_failure $header $tmp_module ../CMakeLists.txt
        done

        popd >/dev/null
    fi
}

########
# MAIN #
########

# Enable globbing
shopt -s globstar

# pika source directory
source_dir=/pika/source
# Where to write the dependencies output files
output_dir=/tmp
# Helper to filter out the dependencies from other groups
module_groups=(pika)

pushd $source_dir/libs >/dev/null

# Extract the list of the modules
modules_list=($(find . -mindepth 2 -maxdepth 2 -type d | sed "s|^\./||" | sort))

# Create a module list per module group
declare -A group_modules=()
for group in "${module_groups[@]}"; do
    group_modules[$group]="$(cd $group >/dev/null && find . -maxdepth 1 \
        -type d ! -path . | sed "s|\./||" && cd .. >/dev/null)"
done

# Construct a list for each of the module groups

echo "" >$output_dir/missing_files.txt
echo "" >$output_dir/missing_deps.txt

# Iterate on all modules of the libs/ dir
for module in "${modules_list[@]}"; do
    pushd ${module} >/dev/null

    module_group=$(dirname $module)
    group_list=${group_modules[$module_group]}
    check_module_dependencies $module "${group_list[@]}" >>$output_dir/missing_deps.txt
    check_cmakelists_files $module include >>$output_dir/missing_files.txt
    check_cmakelists_files $module src >>$output_dir/missing_files.txt

    popd >/dev/null

done
