from OSM_outils.OMSnx_enregistrement import OMSnx_enregistrement
from OSM_outils.OSMnx_recuperation_graph_information import OSMnx_recuperation_graph_information
from django import forms
from django.core.exceptions import ValidationError
from recuperateur_reseau_viaire.models import Graph_viaire_ville_information, Ville
import os

class Graph_viaire_ville_informationForm(forms.Form):
    """
    Cette méthode permet de créer une nouvelle donnée dans la table Graph_viaire_ville_information

    """
    gvvi_nom = forms.CharField(required=True, label="nom de la ville ")

    def __init__(self, *args, **kwargs):
        """
        Cette initialisation de formulaire permet de créer la liste de nom de ville si plusieurs sont entrés dans le
        formulaire

        :param args:
        :param kwargs: dictionnaire ayant pour contenu le nom des villes envoyé par le formulaire
        """
        super(Graph_viaire_ville_informationForm, self).__init__(*args, **kwargs)
        self.validation_erreur_liste = []
        initial_arguments = kwargs.get('initial', None)
        self.liste_nom_ville = None
        if len(args) > 0 and len(args[0].getlist("gvvi_nom_ajout", default=[])) > 1:
            self.liste_nom_ville = [args[0].getlist("gvvi_nom")[0].strip()]
            for nom_ville in args[0].getlist("gvvi_nom_ajout"):
                #vérifie que toutes les villes englobées sont uniques
                nom_ville = nom_ville.strip()
                if nom_ville in self.liste_nom_ville:
                    self.validation_erreur_liste.append(ValidationError({"gvvi_nom_ajout": 'plusieurs villes englobées portent le même nom'}, code='present',
                                          params={'gvvi_nom': nom_ville}))
                self.liste_nom_ville.append(nom_ville)

    def clean(self):
        """
        Cette fonction permet de créer notre propre test de validation en fonction du retour de OSMnx
        """
        if len(self.validation_erreur_liste) != 0:
            raise ValidationError(self.validation_erreur_liste)
        cleaned_data = super(Graph_viaire_ville_informationForm, self).clean()
        if self.liste_nom_ville is not None:
            nom_ville = self.liste_nom_ville
        else :
            nom_ville = cleaned_data['gvvi_nom']
        if isinstance(nom_ville, list):
            nom_fichier = nom_ville[0]
            nom_ville = nom_ville[1:]
        else:
            nom_fichier = nom_ville
        G = self.validation_nom_ville(nom_ville, nom_fichier)
        recuperateur = OSMnx_recuperation_graph_information(G)
        OMSnx_enregistrement.sauvegarde_graphique(G, nom_fichier)
        try:
            lecture_imposible = False
            print("test lecture graph")
            OMSnx_enregistrement.lire_graphe(nom_fichier)
        except ValueError:
            lecture_imposible = True

        if lecture_imposible:
            self.reecriture_fichier_contenant_yes_no(nom_fichier)

        G = OMSnx_enregistrement.recuperer_graphe_viaire_ville(nom_ville)
        try:
            cleaned_data = recuperateur.recuperation_information_graphe(G)
        except Exception as err:
            raise ValidationError({"gvvi_nom" : err.__str__()}, code='invalid',
                            params={'gvvi_nom': nom_ville})
        cleaned_data['gvvi_nom'] = nom_fichier
        return cleaned_data

    def reecriture_fichier_contenant_yes_no(self, nom_fichier):
        """
        Le but de ce fichier est de réécrire le fichier contenant des valeurs yes/no en True/False
        pour la clef oneway uniquement

        """
        chemin = OMSnx_enregistrement.chemin_vers_fichier_ville(nom_fichier)
        with open(chemin, "r") as fichier:
            lignes = fichier.readlines()
        key_one_way = None
        with open(chemin + "_copy", "w") as fichier:
            for ligne in lignes:
                if "oneway" in ligne and key_one_way is None:
                    key_one_way = 'key="' + ligne.split("key id=\"")[1].split('"')[0] + '"'
                if key_one_way is not None and key_one_way in ligne:
                    ligne = ligne.replace("yes", "True")
                    ligne = ligne.replace("no", "False")
                fichier.write(ligne)
        # si l'algorithme n'a pas crashé, on supprime le fichier d'origine et on renomme le fichier copy
        os.remove(chemin)
        os.rename(chemin + "_copy", chemin)

    def validation_nom_ville(self, nom_ville, nom_fichier):
        """
                Cette fonction permet d'analyser les retours de l'argument G qui est le retour de la méthode
                OMSnx_enregistrement.recuperer_graphe_viaire_ville et de lever les erreurs.

                :param G: retour
                :raises ValidationError : si la ville est incconnue de OSMnx ou qu'elle ne possède pas de routes
        """
        ville = Ville.objects.filter(ville_nom=nom_fichier)
        if ville.exists() and Graph_viaire_ville_information.objects.filter(ville=ville[0].ville).exists():
            raise ValidationError({"gvvi_nom" : 'ville déjà enregistrée dans la base de donnée'}, code='present',
                              params={'gvvi_nom': nom_ville})
        try:
            G = OMSnx_enregistrement.lire_graphe(nom_fichier)
        except FileNotFoundError:
            try :
                G = OMSnx_enregistrement.recuperer_graphe_viaire_ville(nom_ville)
                if G is not None:
                    G.name = nom_fichier
            except ValueError as v:
                raise ValidationError({"gvvi_nom" : 'ville non trouvée : ' + v.__str__().split("\"")[1]}, code='invalid',
                                      params={'gvvi_nom': nom_ville})
        return G

    def clean_nb_intersection(self):
        data = self.cleaned_data['gvvi_nb_intersection']
        return data

    def clean_nom(self):
        data = self.cleaned_data['gvvi_nom']
        return data