from django.shortcuts import get_object_or_404, render
import os
from django.conf import settings
# Create your views here.
from django.http import HttpResponse

from recuperateur_reseau_viaire.forms import Graph_viaire_ville_informationForm, \
    Graph_viaire_ville_informationFormUpdate, Graph_viaire_ville_informationForm_delete, \
    Graph_viaire_ville_informationForm_export
from recuperateur_reseau_viaire.models import Graph_viaire_ville_information

from recuperateur_reseau_viaire.admin import Graph_viaire_ville_informationResource
from OSM_outils.OSMnx_recuperation_graph_information import OSMnx_recuperation_graph_information
from OSM_outils.OMSnx_enregistrement import OMSnx_enregistrement


def index(request):
    """
    Cette méthode permet de gérer entre :
     - la mise à jour de plusieurs lignes de la table
     - l'affichage de la table "Graph_viaire_ville_informationResource" de la base de données.

    :param request:
    :return: une HttpResponse de la page index.html en cas d'affichage de la table
    "Graph_viaire_ville_informationResource" le retour de la view update en cas de mise à jour de plusieurs lignes de la
     table en simultané. La création de la HttpResponse se fait à l'aide de django.template.loader.render_to_string().
    """
    if request.GET.__contains__("bouton") and request.GET.getlist("bouton")[0] == "update" \
            and request.GET.__contains__("update"):
        return update(request, request.GET.getlist("update"))
    else:
        form = Graph_viaire_ville_informationForm()
        graph_viaire_ville_information_list = Graph_viaire_ville_information.objects.all()
        return render(request, 'recuperateur_reseau_viaire/index.html',
                      {'list_graph': graph_viaire_ville_information_list, 'form': form})


def valide(request):
    """
    Cette méthode a pour but de dire à l'utilisateur qu'une action viens de se terminer

    :param request:
    :return:
    """
    print("valide !! ")
    return render(request, 'recuperateur_reseau_viaire/valide.html')


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:
    """
    if isinstance(graph_id, int):
        graph_viaire_ville_information_instance = Graph_viaire_ville_information.objects.filter(id=graph_id)[0]
    elif isinstance(graph_id, list):
        graph_viaire_ville_information_instance = []
        for id in graph_id:
            graph_viaire_ville_information_instance.append(Graph_viaire_ville_information.objects.filter(id=id)[0])
    else:
        return 1
    if request.method == 'POST':
        form_u = Graph_viaire_ville_informationFormUpdate(request.POST,
                                                          initial={'valeur': graph_viaire_ville_information_instance})
        if form_u.is_valid():
            var_OSMnx_recuperation_graph_information = OSMnx_recuperation_graph_information(None)
            liste_fonction_recup_graph_information = var_OSMnx_recuperation_graph_information.sgbd_liste_fonction()
            tableau_associatif_nom_variable_nom_fonction = {}
            for func in liste_fonction_recup_graph_information:
                retour = getattr(var_OSMnx_recuperation_graph_information, func)(None)
                nom_variable_sgbd = next(iter(retour))
                tableau_associatif_nom_variable_nom_fonction[nom_variable_sgbd] = {"nom_fonction": func}
            if not isinstance(graph_viaire_ville_information_instance, list):
                graph_viaire_ville_information_instance = [graph_viaire_ville_information_instance]
            for gvvi_instance in graph_viaire_ville_information_instance:
                G = OMSnx_enregistrement.lire_graphe(gvvi_instance.gvvi_nom)
                var_OSMnx_recuperation_graph_information = OSMnx_recuperation_graph_information(G)
                for sgbd_var in dir(graph_viaire_ville_information_instance[0]):
                    if sgbd_var.startswith("gvvi_") and not sgbd_var.endswith("_check"):
                        if form_u.cleaned_data.get(sgbd_var + '_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 form_u.cleaned_data.get(sgbd_var) is not None:
                            if sgbd_var == "gvvi_nom":
                                if Graph_viaire_ville_information.objects.filter(
                                        gvvi_nom=form_u.cleaned_data[sgbd_var]).exists():
                                    continue
                                elif sgbd_var == "gvvi_nom" and \
                                        not Graph_viaire_ville_information.objects.filter(
                                            gvvi_nom=form_u.cleaned_data[sgbd_var]).exists():
                                    try:
                                        OMSnx_enregistrement.renommer_fichier_graphml(gvvi_instance.gvvi_nom,
                                                                                      form_u.cleaned_data[sgbd_var])
                                        gvvi_instance.__setattr__(sgbd_var, form_u.cleaned_data[sgbd_var])
                                    except ValueError:
                                        continue
                            gvvi_instance.__setattr__(sgbd_var, form_u.cleaned_data[sgbd_var])
                gvvi_instance.save()
            return valide(request)
    else:
        form_u = Graph_viaire_ville_informationFormUpdate(initial={'valeur': graph_viaire_ville_information_instance})
        return render(request, "recuperateur_reseau_viaire/update.html", {'form_u': form_u})


def delete(request, graph_id):
    graph_viaire_ville_information_instance = Graph_viaire_ville_information.objects.filter(id=graph_id)[0]
    if request.method == 'POST':
        form_u = Graph_viaire_ville_informationForm_delete(request.POST,
                                                           initial={'valeur': graph_viaire_ville_information_instance})
        if form_u.is_valid():
            graph_viaire_ville_information_instance.gvvi_nom = form_u.cleaned_data['gvvi_nom']
            graph_viaire_ville_information_instance.gvvi_nb_intersection = form_u.cleaned_data['gvvi_nb_intersection']
            if os.path.isfile(os.path.join(settings.REGISTER_DIR, form_u.cleaned_data['gvvi_nom'] + ".graphml")):
                os.remove(os.path.join(settings.REGISTER_DIR, form_u.cleaned_data['gvvi_nom'] + ".graphml"))
            graph_viaire_ville_information_instance.delete()
            return valide(request)
    else:
        form_u = Graph_viaire_ville_informationForm_delete(initial={'valeur': graph_viaire_ville_information_instance})
        return render(request, "recuperateur_reseau_viaire/delete.html", {'form_d': form_u})


def export(request):
    if request.method == 'POST':
        form_e = Graph_viaire_ville_informationForm_export(request.POST,
                                                           initial={'formats_exports': format})
        if form_e.is_valid():
            sgbd_donnees = getattr(Graph_viaire_ville_informationResource().export(),
                                   Graph_viaire_ville_information.formats_exports[
                                       int(form_e.cleaned_data['choix_format_export'])][1])()
            fichier = open(settings.REGISTER_DIR + "/export_sgbd." + Graph_viaire_ville_information.formats_exports[
                int(form_e.cleaned_data['choix_format_export'])][1].removeprefix("get_"), "w")
            fichier.write(sgbd_donnees)
            fichier.close()
            graph_viaire_ville_information_instance = Graph_viaire_ville_information()
            return valide(request)

    else:

        form_e = Graph_viaire_ville_informationForm_export(request.POST,
                                                           initial={'formats_exports': format})
        return render(request, 'recuperateur_reseau_viaire/export.html', {'form_e': form_e})


def atributs_graph(request, graph_id):
    graph = get_object_or_404(Graph_viaire_ville_information, graph_id)
    return render(request, 'recuperateur_reseau_viaire/graph_id.html', {'graph': graph})


def telecharge_liste_commune(request):
    """
    Cette méthode a pour but de créer un formulaire de création de communes. Les communes peuvent être soit téléchargé
    seule, soit en en groupe.

    Elle reçoit une requête de récupération GET pour la création du formulaire et une requête de modification de la base
    de donnée POST à la fin de la validation du formulaire.

    :param request:
    :return: une HttpResponse de la page telecharge_liste_commune.html pour la création du formulaire et sa validation
    et valide.html en cas de validation du formulaire à l'aide de django.template.loader.render_to_string().
    """
    if request.method == "GET":
        form = Graph_viaire_ville_informationForm()
        return render(request, 'recuperateur_reseau_viaire/telecharge_liste_commune.html',
                      {'form': form})
    else:
        form = Graph_viaire_ville_informationForm(request.POST)
        if form.is_valid():
            graph_viaire_ville_information_instance = Graph_viaire_ville_information()
            for clef in form.cleaned_data.keys():
                graph_viaire_ville_information_instance.__setattr__(clef, form.cleaned_data[clef])
            graph_viaire_ville_information_instance.save()
            return valide(request)
        else:
            nom_villes = request.POST.getlist("gvvi_nom_ajout")
            return render(request, 'recuperateur_reseau_viaire/telecharge_liste_commune.html',
                      {'form': form, 'nom_villes_ajout' : nom_villes})
