# env/bin/bash sh

# Ce programme a pour but d'automatiser l'ajout de colonne dans la table Graph_viaire_ville_information de l'application recuperateur_reseau_viaire
# Nous allons nous baser sur la doc https://docs.djangoproject.com/fr/4.1/topics/migrations/
. demande_y_n.sh

# constantes erreurs retours de fonctions
EXIT_SUCCESS=0
EXIT_ERROR=1

function modifie_model()
{
  #cette fonction permet de modifier le fichier model de l'application recuperateur_reseau_viaire
  # elle reçoit en paramètre le type et le nom de la nouvelle variable à rajouter dans le model
  type=$1
  nomvariable=$2
  #le chemin du fichier tampon à remplir au fur et à mesure
  chemin_cible=./../recuperateur_reseau_viaire/_models
  #le chemin vers le model de l'application recuperateur_reseau_viaire
  chemin_vers_model=./../recuperateur_reseau_viaire/models.py

  if grep -qw "$nomvariable" "$chemin_vers_model"
  then
    return 0
  fi

  #permet de récupérer le numéro de la ligne du début de la classe Model
  ligne_debut_classe=$(grep -n 'class Graph' $chemin_vers_model)
  ligne_debut_classe=$(echo "$ligne_debut_classe" | cut -d ':' -f 1)

  #affiche le texte jusqu'au début de la classe dans un nouveau fichier
  awk "NR<=$ligne_debut_classe{print \$0}" < $chemin_vers_model > $chemin_cible

  #ajoute au début de la classe la nouvelle variable
  echo -e "\t$nomvariable = models.$type()" | expand -t 4 >> $chemin_cible

  #affiche le reste du fichier
  ligne_debut_classe=$((ligne_debut_classe + 1))
  awk "NR>=$ligne_debut_classe{print \$0}" $chemin_vers_model >> $chemin_cible

  #réécris le fichier model d'origine avec le nouveau fichier puis supprime le fichier tampon
  cat $chemin_cible > $chemin_vers_model
  rm $chemin_cible
}


function modifie_methode_migration_vide()
{
  #cette fonction permet de modifier le nouveau fichier de migration de donnée en lui ajoutant le lien vers la nouvelle
  #fonction de remplissage de la base de donnée. Cette migration de donnée pourra alors permettre de remplir la nouvelle
  #colonne des données anciennes
  #elle prends en paramètre le nom de la nouvelle variable et le nom de la fonction de récupération de fonction
  nom_variable=$1
  nom_fonction=$2

  #le chemin vers le dossier des migrations de l'application recuperateur_reseau_viaire
  chemin_vers_migration=./../recuperateur_reseau_viaire/migrations/
  #le chemin du fichier tampon à remplir au fur et à mesure
  chemin_vers_cible=./../recuperateur_reseau_viaire/migrations/_migration_tampon
  #récupère le fichier migration contenant le mot _auto_ et ayant le numéro le plus élevé en début de nom (le plus récent)
  dernier_fichier_migration=$(find "$chemin_vers_migration" -name "__pycache__" -prune -o -name '*_auto_*' -print | sort -n | tail -1)
  #chemin vers le fichier model de méthode nécessaire pour ajouter des données dans les lignes de la table existant
  chemin_fichier_fonction_ajout_model=./migration_fichier_model
  #permet de récupérer le numéro de la ligne du début de la classe Migration
  ligne_debut_classe=$(grep -n 'class Migration' "$dernier_fichier_migration")
  ligne_debut_classe=$(echo "$ligne_debut_classe" | cut -d ':' -f 1)

  #récupère le numéro de ligne dans le fichier pour ajouter un appelle de méthode à l'avant dernière ligne
  nb_ligne_model=$(wc -l < "$dernier_fichier_migration")
  {
    #affiche les lignes du fichier jusqu'à la ligne de début de classe exclue
    awk "NR<$ligne_debut_classe{print \$0}" "$dernier_fichier_migration"
    #ajoute un fichier de méthode model à toutes les migrations en remplaçant les cases tel que :
    # le nouveau nom de la variable
    # le nom dee la méthode de récolte de donnée OSMnx_recuperation_graph_information
    sed -s "s/&&nom_variable&&/$nom_variable/g" "$chemin_fichier_fonction_ajout_model" | sed -s "s+&&nom_fonction&&+$nom_fonction+g"
    echo -e "\n"
    #afiche toute la classe de migration excepté la dernière ligne
    awk "($ligne_debut_classe <= NR && NR < $nb_ligne_model){print \$0}" "$dernier_fichier_migration"
    #ajout de l'appel de fonction
    echo -e "\t\tmigrations.RunPython(ajoute_donnees_nouvelle_colonne)" | expand -t 4
    echo -e "\t]" | expand -t 4
  } > "$chemin_vers_cible"

  #réécris le fichier Migration d'origine avec le nouveau fichier puis supprime le fichier tampon
  cat $chemin_vers_cible > "$dernier_fichier_migration"
  rm $chemin_vers_cible
}

function modifie_template_index()
{
  # Cette fonction permet de modifier le fichier index du template de l'application recuperateur_reseau_viaire
  # cette modification correspond à l'ajout d'une nouvelle colonne dans la table d'affichage de notre base de donnée
  # ele prend en paramètre le nom de la nouvelle variable
  nomvariable=$1

  #chemin vers le fichier index de l'application recuperateur_reseau_viaire
  chemin_vers_template_index=./../recuperateur_reseau_viaire/templates/recuperateur_reseau_viaire/index.html
  #chemin vers fichier_tampon à remplir au fur et à mesure
  chemin_vers_index_tampon=./../recuperateur_reseau_viaire/templates/recuperateur_reseau_viaire/_index.html
  #donne le numéro de la ligne dans le fichier de la fermeture de la première ligne de tableau
  ligne_tr_premier_tr=$(sed -n '1,  /<\/tr>/p' "$chemin_vers_template_index" | wc -l)

  #donne le numéro de la ligne dans le fichier de la fermeture de la case de ligne avant le premier lien
  ligne_avant_premier_lien=$(sed -n '1,  /<a /p' "$chemin_vers_template_index" | wc -l)
  ligne_avant_premier_lien=$((ligne_avant_premier_lien - 1))
  {
    #affichage du fichier du début à la ligne de la première fermeture de tr exclue
    awk "NR < $ligne_tr_premier_tr {print \$0}" $chemin_vers_template_index
    #ajout du nom de notre variable
    echo -e "\t<th>$nomvariable</th>" | expand -t 4
    #affichage du reste du fichier jusqu'a la dernière case du premier tableau
    awk "($ligne_tr_premier_tr <= NR && NR < $ligne_avant_premier_lien){print \$0}" $chemin_vers_template_index
    #ajout de notre case
    echo -e "\t\t<td>{{ graph.$nomvariable }}</td>" | expand -t 4
    #ajout début case des liens
    echo -e "\t\t<td>" | expand -t 4
    #affichage du reste du fichier
    sed -n '/<a /, $ p' "$chemin_vers_template_index"
  } > $chemin_vers_index_tampon
  cat $chemin_vers_index_tampon > $chemin_vers_template_index
  rm $chemin_vers_index_tampon

}


function test_fichier_test_associe_a_migration()
{
  # Cette fonction permet d'utiliser le fichier test associé à la migration de donnée
  # si tous les testes ne passent pas on retourne une erreur
  # Elle prend en paramètre le nom du fichier test
  nom_fichier_test=$1

  python ./../manage.py test OSM_outils.Tests."$nom_fichier_test"
  retour=$?
  if [[ $retour -eq 0 ]]
  then
    return $EXIT_SUCCESS
  else
    return $EXIT_ERROR
  fi
}

function ajoute_au_git_fichiers_migration() {
  #
  # Cette fonction a pour but d'ajouter au git les derniers fichier migrations créé.
  #

  #le chemin vers le dossier des migrations de l'application recuperateur_reseau_viaire
  chemin_vers_migration=./../recuperateur_reseau_viaire/migrations

  #récupère le fichier migration contenant le mot _auto_ et ayant le numéro le plus élevé en début de nom (le plus récent)
  derniers_fichiers_migration_auto=$(git status | grep '/recuperateur_reseau_viaire/migrations/[0-9][^_]*')

  for fichier in $derniers_fichiers_migration_auto
  do
      if demande_y_n "ajouter le fichier $fichier au git ? y ou n "
      then
        git add "$fichier"
      fi
  done
}

function main(){
  #Cette fonction a pour but de lancer toutes les fonctions dans le bonne ordre pour
  #faire une migration de schéma et une migration de donnée.
  # Elle a aussi pour but de modifier les fichiers du projets pour ajuster le projet à la nouvelle colonne
  # tel que :
  # - le model
  # - la méthode de migration de donnée dans le fichier plus-haut-nombre_auto_une-date_un-nombre.py
  # - le template index.html
  #le chemin vers le model de l'application recuperateur_reseau_viaire
  chemin_vers_model=./../recuperateur_reseau_viaire/models.py
  #le chemin vers le dossier des migrations de l'application recuperateur_reseau_viaire
  chemin_vers_migration=./../recuperateur_reseau_viaire/migrations
  if [[ -z $VIRTUAL_ENV ]] || [[ -z $(find "$VIRTUAL_ENV" -iname 'django' -type d) ]]
  then
        echo "pour faire tourner ce programme vous devez utiliser l'environment virtuel possédant django"
        exit $EXIT_ERROR
  fi
  if [[ ! (-r ./sauvegarde_var) ]]
  then
    echo "le fichier de sauvegarde de vos choix \"sauvegarde_var\" n'existe pas"
    exit $EXIT_ERROR
  fi

  #chemin vers le fichier de sauvegarde
  fichier_decision_utilisateur_ajout_colonne=./sauvegarde_var
  #lecture des variables depuis le fichier
  valeurs=$(awk '{print $2}' "$fichier_decision_utilisateur_ajout_colonne")
  nomvariable=$(echo "$valeurs" | sed -n '1p')
  type_variable=$(echo "$valeurs" | sed -n '2p')
  nom_fonction=$(echo "$valeurs" | sed -n '3p')
  nom_fichier_test=$(echo "$valeurs" | sed -n '4p')
  # Test de la nouvelle méthode de récupération de données, si la méthode ne renvoie pas une liste de valeur,
  # on fait pas la migration, sinon on arrête le script ici
  test_fichier_test_associe_a_migration "$nom_fichier_test"
  retour=$?
  if [ $retour -ne $EXIT_SUCCESS ]
  then
     echo "tous les tests du fichier test $nom_fichier_test ne sont pas passé"
     exit $EXIT_ERROR
  fi
  modifie_model  "$type_variable" "$nomvariable"
  python ../manage.py makemigrations recuperateur_reseau_viaire
  python ../manage.py makemigrations --empty recuperateur_reseau_viaire
  modifie_methode_migration_vide "$nomvariable" "$nom_fonction"
  #si la migration ne fonctionne pas on supprime la variable du modèle pour que les test puissent fonctionner ensuite
  if ! python ../manage.py migrate
  then
    model_tmp=$(mktemp /tmp/exemple.XXXXXX) || exit $EXIT_ERROR
    grep -v "$nomvariable" "$chemin_vers_model" > "$model_tmp"
    cat "$model_tmp" > "$chemin_vers_model"
    #récupère le fichier migration contenant le mot _auto_ et ayant le numéro le plus élevé en début de nom
    # (le plus récent) et le supprime
    dernier_fichier_migration=$(find "$chemin_vers_migration" -name "__pycache__" -prune -o -name '*_auto_*' -print | sort -n | tail -1)
    rm "$dernier_fichier_migration"
    exit $EXIT_ERROR
  fi
  modifie_template_index "$nomvariable"
  ajoute_au_git_fichiers_migration
}

main
