from OSM_outils.OMSnx_enregistrement import OMSnx_enregistrement
from OSM_outils.OSMnx_recuperation_graph_information import OSMnx_recuperation_graph_information
from django.shortcuts import render
from recuperateur_reseau_viaire.forms import Graph_viaire_ville_informationFormUpdate
from recuperateur_reseau_viaire.models import Graph_viaire_ville_information, Ville, Rassemblement_ville
from .view_valide import valide

def update(request, graph_id):
    """
    Cette méthode permet de mettre à jour une ligne de la table Graph_viaire_ville_information. Elle prend en paramètre
    la requête et la clef primaire.

    Cette méthode permet de gérer l'affichage ainsi que les modifications dans la base de donnée en
    fonction du formulaire compris dans la requête.

    Le formulaire se présente sous la forme suivante : un dictionnaire cleaned_data associant à un champ de formulaire,
    la valeur donné par l'utilisateur. Nous avons ici deux champs de formulaire pour chaque variable de la table
    Graph_viaire_ville_information :
     - le champ et la valeur préremplit par la table ou modifié par l'utilisateur
     - une case à cocher, si la case à cocher lla variable est modifié par la fonction associée dans la classe
     OSMnx_recuperation_graph_information

     Lorsque le nom d'une ville est modifié, nous modifions aussi le nom du fichier. Dans le cas où un nom un autre
     fichier a le même nom, on ne le renomme pas, ni le fichier ni dans la base de donnée.

    en cas de succès la page valide.html est affichée

    :param request:
    :param graph_id:
    :return:
    """
    # la modification peut se faire sur un élément ou une liste
    if isinstance(graph_id, int):
        # on modifie qu'une seule instance de graph_viaire_ville_information et de Ville
        graph_viaire_ville_information_instance = Graph_viaire_ville_information.objects.filter(id=graph_id)[0]
    else:
        # on modifie plusieurs instances de graph_viaire_ville_information et de Ville
        graph_viaire_ville_information_liste_querry = Graph_viaire_ville_information.objects.filter(id__in=graph_id)
        graph_viaire_ville_information_instance = []
        for gvvi in graph_viaire_ville_information_liste_querry:
            graph_viaire_ville_information_instance.append(gvvi)


    if request.method == 'POST':
        # validation ou non et exécution du formulaire modifié par l'utilisateur
        form_u = Graph_viaire_ville_informationFormUpdate(request.POST,
                                                          initial={'valeur': graph_viaire_ville_information_instance})
        if form_u.is_valid():
            action_modification_formulaire_valide(form_u, graph_viaire_ville_information_instance,
                                                  request.POST.getlist("ville_englobe"))
            return valide(request)
        else:
            return render(request, "recuperateur_reseau_viaire/update.html", {'form_u': form_u})
    else:
        # création du formulaire prérempli
        form_u = Graph_viaire_ville_informationFormUpdate(initial={'valeur': graph_viaire_ville_information_instance})
        liste_ville_englobe = []
        # si nous avons une liste d'instance graph_viaire_ville_information nous n'affichons pas les villes englobées
        if not isinstance(graph_viaire_ville_information_instance, list):
            for ville_englobe in Rassemblement_ville.objects.filter(ville_englobante=graph_viaire_ville_information_instance.ville_id):
                #liste_ville_englobe.append(villle_englobe)
                liste_ville_englobe.append(ville_englobe.ville)
        return render(request, "recuperateur_reseau_viaire/update.html",
                      {'form_u': form_u, 'liste_villes_englobe': liste_ville_englobe})


def action_modification_formulaire_valide(form_u, graph_viaire_ville_information_instance, ville_englobee):
    """
    Cette méthode a pour but de modifier une ligne de la table graph_viaire_ville_information ainsi que les tables
    qui en découlent telle la table Rassemblement_ville.

    Les actions effectuées sont :
    - modifier les valeurs de graph_viaire_ville_information_instance en fonction de la checkbox :
        - si elle est cochée ont recalcule le résultat avec la méthode venant de la classe
        OSMnx_recuperation_graph_information
        - ont attribut la nouvelle valeur entrée manuellement
    - on renomme le fichier graphml si on modifie le nom de la ville
    - on supprime les instances de Rassemblement_ville si leurs cases sont cochées

    :param form_u : l'instance de formulaire de modification
    :param graph_viaire_ville_information_instance : l'instance de la table graph_viaire_ville_information que nous
    modifions
    :param ville_englobee : la liste de villes englobees dont la case est cochée pour les supprimmers
    """
    # formulaire valide execution des sauvegarde des modifications
    tableau_associatif_nom_variable_nom_fonction = OSMnx_recuperation_graph_information.\
        creer_tableau_associatif_fonction_variable_table_graph_viaire_ville_information()
    # créé une liste de ville si ce n'est pas une ville pour traiter la suite de la même manière
    if not isinstance(graph_viaire_ville_information_instance, list):
        graph_viaire_ville_information_instance = [graph_viaire_ville_information_instance]

    # modification des tables de la base de donnée
    for gvvi_instance in graph_viaire_ville_information_instance:
        G = OMSnx_enregistrement.lire_graphe(gvvi_instance.ville.ville_nom)
        var_OSMnx_recuperation_graph_information = OSMnx_recuperation_graph_information(G)
        for sgbd_var in form_u.changed_data:
            # récupération des variables de classes de graph_viaire_ville_information dans le formulaire
            # uniquement ceux ayant été modifié (les checkboxes ou les entrées manuelles)
            # case cochée ou non
            if sgbd_var.endswith("_check") or sgbd_var + "_check" in form_u.changed_data:
                sgbd_var = sgbd_var.removesuffix("_check")
                gvvi_instance. \
                    __setattr__(sgbd_var,
                                getattr(var_OSMnx_recuperation_graph_information,
                                        tableau_associatif_nom_variable_nom_fonction[sgbd_var][
                                            "nom_fonction"])(G)[sgbd_var])
            elif sgbd_var != "gvvi_nom":
                gvvi_instance.__setattr__(sgbd_var, form_u.cleaned_data[sgbd_var])
            # modification du nom de la ville à part
            else:
                ville_modification_nom = Ville.objects.filter(ville=gvvi_instance.ville_id)[0]
                OMSnx_enregistrement.renommer_fichier_graphml(ville_modification_nom.ville_nom,
                                                              form_u.cleaned_data["gvvi_nom"])
                ville_modification_nom.ville_nom = form_u.cleaned_data["gvvi_nom"]
                ville_modification_nom.save()
        gvvi_instance.save()
    # supprimmer les villes rassemblées cochées :
    Rassemblement_ville.objects.filter(ville__in=ville_englobee).\
        delete()