#
#  @file check_header.sh
#
#  @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
#                       Univ. Bordeaux. All rights reserved.
#
#  @author Camille Ordronneau
#  
#  @date 2024-07-16
#
# This script check that basic informations is present and correct in
# headers of source files.
#
#!/usr/bin/env sh
header=1
nberr=0

# Print the file name if its the first error in the file
print_header()
{
    if [ $header -ne 0 ]
    then
        echo "------ $1 --------"
        header=0
    fi
}

# Check if there is the name of the file in the header
check_header_file()
{
    filepath=$1
    toto=$( grep " @file $filepath" $filepath )

    if [ $? -ne 0 ]
    then
        print_header $filepath
        echo -n "@file line missing or incorrect:"; grep "@file" $filepath; echo ""
        nberr=$(( nberr + 1 ))
    fi

}

# Check if there is a copyright line in the header, with correct year
check_header_copyright()
{
    filepath=$1

    # Get the year of last modification in the file
    # Get date in YYYY-MM-DD format -> take the first 4 characters
    year=$( git log -1 --pretty="format:%cd" --date=format:%Y $filepath)
    toto=$( grep -E " @copyright 2008-$year Bordeaux INP" $filepath )

    if [ $? -ne 0 ]
    then
        print_header $filepath
        echo -n "@copyright line missing or incorrect:"; grep "@copyright" $filepath; echo "";
    fi
}

# Check if there is at least on author line in the header
check_header_author()
{
    filename=$1
    basename=$( basename $filename )

    toto=$( grep -E " @author " $filename )

    if [ $? -ne 0 ]
    then
        print_header $filename
        echo "@author line missing";
        nberr=$(( nberr + 1 ))
    fi
}

# Check if there is a date line in the header
check_header_date()
{
    filename=$1
    basename=$( basename $filename )

    toto=$( grep -E " @date [0-9]{4}-[01][0-9]-[0-3][0-9]" $filename )
    if [ $? -ne 0 ]
    then
        print_header $filename
        echo -n "@date line missing or incorrect"; grep "@date" $filename; echo "";
        nberr=$(( nberr + 1 ))
    fi
}

check_header_define()
{
    filename=$1
    basename=$( basename $filename )

    case $basename in
        *.hpp)
            n=$( basename $basename .hpp | awk '{print toupper($0)}' )

            macro="${n}_HPP"
            err=0

            toto=$( grep "#ifndef .*$macro" $filename )
            ret=$?
            err=$((err + ret))

            if [ $ret -eq 0 ]
            then
                macro=$( grep "#ifndef" $filename | sed 's/#ifndef //' )
            fi
            toto=$( grep "#define $macro" $filename )
            ret=$?
            err=$((err + ret))

            toto=$( grep "#endif /\* $macro \*/" $filename )
            ret=$?
            err=$((err + ret))

            if [ $err -ne 0 ]
            then
                print_header $filename
                grep "#ifndef" $filename
                grep "#define" $filename
                grep "#endif"  $filename
                nberr=$(( nberr + 1 ))
            fi
            ;;
        *)
    esac

}

#
# Launch a check for each one of these lines
#
# @file filename
# @copyright
# @author
# @date
#
check_header()
{
    header=1
    check_header_file $1
    check_header_copyright $1
    check_header_author $1
    check_header_date $1
    
    # For now there is still a lot of files to change so they all have the same define format
    # So this verification is not done
    # This could be used later
    # check_header_define $1
}

#
# Get the files to check
#
files=$(git ls-files '*.cpp' '*.hpp' '*.c' '*.h'    |
        grep -v "externals/*"                       |
        grep -v "src/trace/portable_*"              |
        grep -v "src/core/getopt.*"                 )

if [ $# -gt 0 ]
then
    files=$*
fi

# For eac file the check is applied
for f in $files
do
    if [ -d $f ]
    then
        continue;
    fi

    check_header $f
done

# If there is any error, the number of errors is printed
if [ $nberr -gt 0 ]
then
    echo "${nberr} mistakes have been found in the header files."
    exit 1
else
    exit 0
fi
