"""
 @file generation_utils.py

 @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
                      Univ. Bordeaux. All rights reserved.

 @author Camille Ordronneau

 @date 2024-07-16
 
 Script to automatically update the header of every files in the project
"""
import time
import subprocess

# Normalized author names in the format : Login -> Firstname Lastname
authors_name_dict = {
    "Arthur CHEVALIER"          : "Arthur Chevalier",
    "Arthur Redondy"            : "Arthur Redondy",
    "Augustin Degomme"          : "Augustin Degomme",
    "augustin"                  : "Augustin Gauchet",
    "Camille Ordronneau"        : "Camille Ordronneau",
    "Ordronneau Camille"        : "Camille Ordronneau",
    "Cédric Augonnet"           : "Cedric Augonnet",
    "Clément Vuchener"          : "Clement Vuchener",
    "Florent Pruvost"           : "Florent Pruvost",
    "Francois Broquedis"        : "Francois Broquedis",
    "François Trahay"           : "Francois Trahay",
    "Francois Trahay"           : "Francois Trahay",
    "francois.trahay"           : "Francois Trahay",
    "BENMENDIL Hamza"           : "Hamza Benmendil",
    "BAHHOU Houssam"            : "Houssam Bahhou",
    "Elomariismail00"           : "Ismail Elomari Alaoui",
    "Jean-Alexandre Collin"     : "Jean-Alexandre Collin",
    "Jérémie Gaidamour"         : "Jeremie Gaidamour",
    "Laszlo Joel"               : "Joel Laszlo",
    "Johnny Jazeix"             : "Johnny Jazeix",
    "Jonnhy Jazeix"             : "Johnny Jazeix",
    "Jule Marcoueille"          : "Jule Marcoueille",
    "Kevin Coulomb"             : "Kevin Coulomb",
    "DIEU Killian"              : "Killian Dieu",
    "Killian Dieu"              : "Killian Dieu",
    "Tackwin"                   : "Luca Bourroux",
    "Luca Bourroux"             : "Luca Bourroux",
    "GUEDON Lucas"              : "Lucas Guedon",
    "Lucas G"                   : "Lucas Guedon",
    "CANNAROZZO Luigi"          : "Luigi Cannarozzo",
    "THIOLIERE Martin"          : "Martin Thioliere",
    "Mathieu Faverge"           : "Mathieu Faverge",
    "BOULLIT Mohamed_Faycal"    : "Mohamed Faycal Boullit",
    "Nicolas Richart"           : "Nicolas Richart",
    "nbredel"                   : "Nolan Bredel",
    "Olivier Lagrasse"          : "Olivier Lagrasse",
    "Pascal Noisette"           : "Pascal Noisette",
    "Philippe SWARTVAGHER"      : "Philippe Swartvagher",
    "Samuel Thibault"           : "Samuel Thibault",
    "Thibault Soucarre"         : "Thibault Soucarre",
    "Thomas Herault"            : "Thomas Herault",
    "Xavier Lacoste"            : "Xavier Lacoste",
    ""                          : "",
}

def file_authors(filepath):
    '''
        Return authors of a file
    '''

    # Get every line changes -> Get author -> Remove duplicate -> Remove first word "author" to only get the author name
    command = f'git blame "{filepath}" --porcelain | grep  "^author " | sort -u | cut -d " " -f 2-'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    authors = result.stdout.strip().split("\n")

    if "Not Committed Yet" in authors:
        authors.remove("Not Committed Yet")

    if "root" in authors:
        authors.remove("root")

    # Convert to real normalized names
    authors = [authors_name_dict[a] for a in authors]

    # Remove duplicate
    authors = list(set(authors))

    authors_list_string = ""

    for a in authors:
        authors_list_string += " * @author "
        authors_list_string += a
        authors_list_string += "\n"

    return authors_list_string

def file_date(filepath):
    '''
        Return date of last modification
    '''

    command = f'git log -1 --pretty="format:%cs" {filepath}'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    return result.stdout.strip()

def create_header(filepath):
    command = f'git log -1 --pretty="format:%cs" "{filepath}" | cut -c-4'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    last_change_year = result.stdout.strip()
    return '''/**
 *
 * @file '''+ filepath +'''
 *
 * @copyright 2008-'''+ last_change_year +''' Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
''' + file_authors(filepath) + ''' *
 * @date ''' + file_date(filepath) + '''
 */'''

def update_header(filepath):
    global file_error_list
    with open(filepath, 'r') as file:
        lines = file.readlines()
    

    if lines[0].strip() != "/**" :
        print("\n[ERROR] : File " + filepath + " has not the right header format")
        print("It seems like the file " + filepath + " does not already contains any header in the current project format.")
        print("This could be because the file has seen its header removed or is a new file.\n")
        print("If you want to take into account this file in the header update please put :\n/**\n *\n */\n\nAt the beginning of the file.")
        print("If you want to remove this error without updating the file :")
        print("  - Go to file " + __file__ + " and edit the 'command' variable inside the 'project_file_list' function.\n")
        file_error_list.append(filepath)
        return

    if is_file_up_to_date(filepath):
        return

    # Take the first line equal to "*/"
    header_end_line = 0
    for i, line in enumerate(lines):
        if line.strip() == "*/" :
            header_end_line = i + 1
            break
    
    # Format the header to a list of lines
    header = create_header(filepath).split("\n")
    header = [line + "\n" for line in header]

    # Put in place the new header
    new_file_content = header + lines[header_end_line:]

    # Write it to the file
    with open(filepath, 'w') as file:
        file.writelines(new_file_content)

def is_file_up_to_date(filepath):

    command = f'git log -1 --pretty="format:%cs" {filepath}'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    last_change_date = result.stdout.strip()

    command = f'grep "@date" {filepath} | cut -d \' \' -f 4'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    header_date = result.stdout.strip()

    return header_date == last_change_date

def project_file_list():
    '''
        Return authors of a file
    '''

    command = f'''
    git ls-files '*.cpp' '*.hpp' '*.c' '*.h'    |
    grep -v "externals/*"                       |
    grep -v "src/trace/portable_*"              |
    grep -v "src/core/getopt.*"                      
    '''
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    file_list = result.stdout.strip().split("\n")

    return file_list

file_error_list = []

for filepath in project_file_list():
    update_header(filepath)

if file_error_list != []:
    print("File that caused an error :")
    for file in file_error_list:
        print("  - " + file)
