import os.path
from collections import Counter

import osmnx as ox
from django.conf import settings
import networkx as nx


class OSMnx_recuperation_graph_information:
    """
         Cette classe a pour but de récupérer toutes les informations d'un graph que nous voullons garder
     dans notre base de donnée.
    """

    def recuperation_information_graphe(self, G):
        """
        Cette méthode a pour but de récupérer les informations importantes du graphe. Les informations sont
        ensuite stockées dans un dictionnaire de la manière suivante :
        'clef sgbd' => résultat
        puis retournés.
        :param G: graphe OSMnx dont nous voullons extraire les informations
        :return: dictionnaire représentatn les informations importantes du graphe à stocker
        """
        dict_retour = {}
        liste_recupere_info = [func for func in dir(self) if callable(getattr(self, func)) and func.startswith("get")]
        id_fct = 0
        for fct in liste_recupere_info:
            print(fct, " : ", id_fct, " sur ", len(liste_recupere_info))
            dict_retour.update(getattr(self, fct)(G))
            id_fct = id_fct + 1
        return dict_retour

    @staticmethod
    def get_recuperation_osmnx_basic_information(G):
        """
        Cette méthode à pour but de récupérer les informations de statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre.

        :param G: Le graph du quelle nous voulons extraire les informations
        :return: retourne les statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre
        """
        dict_retour = {}
        basic_statistique = ox.basic_stats(G)
        dict_retour['gvvi_nb_intersection'] = basic_statistique['intersection_count']
        return dict_retour

    @staticmethod
    def lire_graphe(gvvi_nom):
        """
        Cette méthode permet de lire dans le dossier Data un grapml grâce au nom entré en paramètre.
        Ce paramètre doit être le nom de la ville sans le chamin ni l'extension graphml

        :param gvvi_nom: Le nom de la ville associé à un graphe dont nous voulons récupérer le graph.
        """
        path = os.path.join(settings.REGISTER_DIR + "/" + gvvi_nom + ".graphml")
        return ox.load_graphml(path)

    @staticmethod
    def get_diametre(G, shortest_path_lengths=None):
        """
        Cette méthode à pour but de récupérer les informations de statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre.

        :param G: Le graph du quelle nous voulons extraire les informations
        :return: retourne les statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre
        """
        dict_retour = {}
        #permettre d'éviter de calculer plusieurs fois le plus cours chemin'
        try:
            dict_retour['gvvi_diametre'] = nx.diameter(G)#max(nx.eccentricity(G, sp=shortest_path_lengths).values())
        except nx.NetworkXError:
            dict_retour['gvvi_diametre'] = nx.diameter(G.to_undirected())
        return dict_retour

    @staticmethod
    def get_degre_moyen(G):
        """
        Cette méthode à pour but de récupérer les informations de statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre.

        :param G: Le graph du quelle nous voulons extraire les informations
        :return: retourne les statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre
        """
        dict_retour = {}
        dict_retour['gvvi_degre_moyen'] = ox.basic_stats(G)['k_avg']
        return dict_retour

    @staticmethod
    def get_connectivity(G):
        """
        Cette méthode à pour but de récupérer les informations de statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre. Cette statistique est la connectivité du graph

        :param G: Le graph du quelle nous voulons extraire les informations
        :return: retourne les statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre
        """
        dict_retour = {}
        dict_retour['gvvi_connectivity'] = nx.number_of_edges(G) / (3 * (nx.number_of_nodes(G) - 2))
        return dict_retour

    @staticmethod
    def get_planning_vs_self_organised_cities(G):
        """
        Cette méthode à pour but de récupérer les informations de statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre. Ici nous calculons un ratio organic permettant de discriminer les graphes
        de ville plannifié aux graphes de villes autoorganisé.

        :param G: Le graph du quelle nous voulons extraire les informations
        :return: retourne les statistiques basic que peut nous fournir la OSMnx
        sur le graphe entré en paramètre
        """
        dict_retour = {}
        orgvs = Counter(d for n, d in G.degree())
        dict_retour['gvvi_org_plan_vs_organized'] = (orgvs[1] + orgvs[3]) / nx.number_of_edges(G)
        return dict_retour
