#!/usr/bin/env python3


from collections import deque
import math as ma
import matplotlib.pyplot as plt

#%% Graphes exemples G1 et G2

G1={'A': {'adj': {'C': 3, 'F': 1}, 'XY':(6, 1.5)},\
    'B': {'adj': {'C': 2, 'E': 1, 'D': 3}, 'XY':(1.5, 3)},\
    'C': {'adj': {'A': 3, 'B': 2, 'E': 3, 'F': 1}, 'XY':(4.5, 3)},\
    'D': {'adj': {'B': 3, 'E': 1}, 'XY':(0, 1.5)},\
    'E': {'adj': {'B': 1, 'C': 3, 'D': 1, 'F': 5}, 'XY':(1.5, 0)},\
    'F': {'adj': {'A': 1, 'C': 1, 'E': 5}, 'XY':(4.5, 0)}}

G2={'A11': {'adj': {'A12': 1, 'A21': 1}, 'XY': (1, 1)},
 'A12': {'adj': {'A11': 1, 'A13': 1}, 'XY': (1, 2)},
 'A13': {'adj': {'A12': 1, 'A14': 1}, 'XY': (1, 3)},
 'A14': {'adj': {'A13': 1, 'A15': 1}, 'XY': (1, 4)},
 'A15': {'adj': {'A14': 1, 'A25': 1}, 'XY': (1, 5)},
 'A21': {'adj': {'A11': 1, 'A31': 1}, 'XY': (2, 1)},
 'A25': {'adj': {'A15': 1, 'A35': 1}, 'XY': (2, 5)},
 'A31': {'adj': {'A21': 1, 'A32': 1, 'A41': 1}, 'XY': (3, 1)},
 'A32': {'adj': {'A31': 1, 'A33': 1, 'A42': 1}, 'XY': (3, 2)},
 'A33': {'adj': {'A32': 1, 'A34': 1, 'A43': 1}, 'XY': (3, 3)},
 'A34': {'adj': {'A33': 1, 'A35': 1, 'A44': 1}, 'XY': (3, 4)},
 'A35': {'adj': {'A25': 1, 'A34': 1, 'A45': 1}, 'XY': (3, 5)},
 'A41': {'adj': {'A31': 1, 'A42': 1, 'A51': 1}, 'XY': (4, 1)},
 'A42': {'adj': {'A32': 1, 'A41': 1, 'A43': 1, 'A52': 1}, 'XY': (4, 2)},
 'A43': {'adj': {'A33': 1, 'A42': 1, 'A44': 1, 'A53': 1}, 'XY': (4, 3)},
 'A44': {'adj': {'A34': 1, 'A43': 1, 'A45': 1, 'A54': 1}, 'XY': (4, 4)},
 'A45': {'adj': {'A35': 1, 'A44': 1, 'A55': 1}, 'XY': (4, 5)},
 'A51': {'adj': {'A41': 1, 'A52': 1}, 'XY': (5, 1)},
 'A52': {'adj': {'A42': 1, 'A51': 1, 'A53': 1}, 'XY': (5, 2)},
 'A53': {'adj': {'A43': 1, 'A52': 1, 'A54': 1}, 'XY': (5, 3)},
 'A54': {'adj': {'A44': 1, 'A53': 1, 'A55': 1}, 'XY': (5, 4)},
 'A55': {'adj': {'A45': 1, 'A54': 1}, 'XY': (5, 5)}}

#%%

# Fonctions pour ajouter un sommet ou une liste de sommets à un graphe

def sommet(G,s):
    if s not in G:
        G[s]={"adj":{}}

def sommets(S):
    G={}
    for s in S:
        sommet(G,s)
    return G

def arete(G,s,t,p):
    """Ajoute au graphe G une arete de poids p entre les sommets s et t"""
    sommet(G,s)
    sommet(G,t)
    G[s]["adj"][t]=p
    G[t]["adj"][s]=p

def aretes(G,A):
    """Ajoute la liste des aretes ponderees A au graphe G
    Entrees :
        G : graphe pondere
        A : liste de triplets s,t,p"""
    for s,t,p in A:
        arete(G,s,t,p)

#%% Pour les tracés

JAUNE  =  "yellow"      #  couleur  des  sommets  non  explorés
BLEU  =  "blue"        #  couleur  des  sommets  explorés (mais pas tous ses voisins)
ROUGE  =  "red"

def ext_comp(G,cle):
    gext = {}
    for i in G:
        gext[i]=G[i][cle]
    return gext

def convert_tot(dXY):
    x,y = [],[]
    for v in dXY.values():
        x.append(v[0])
        y.append(v[1])
    return x,y

def convert_tot_coul(dcouleurs):
    L = []
    for v in dcouleurs.values():
        L.append(v)
    return L


def trace_graphe_adj(G,s=(20)**2,etiquettes=True,transpg=0.5,transpa=0.15):
    dXY,dadj = ext_comp(G,'XY'), ext_comp(G,'adj')
    fig, ax = plt.subplots(figsize = (10,7))
    color = 'blue'
    x,y = convert_tot(dXY)
    plt.scatter(x, y, s, c=color, alpha=transpg)
    if etiquettes==True:
        for c in dadj :
            ax.annotate(c, dXY[c], size = 15, va="center", ha="center")
    for c in dadj:
        for j in dadj[c]:
           X = [dXY[c][0],dXY[j][0]]
           Y = [dXY[c][1],dXY[j][1]]
           ax.plot(X, Y, color="blue", alpha = transpa)
    plt.show()

def trace_graphe_adj_cc(G,d=(20)**2,etiquettes=True, transpg=0.5):
    dXY,dadj,dcouleurs = ext_comp(G,'XY'), ext_comp(G,'adj'), ext_comp(G,'coul')
    transpa = 0.2
    fig, ax = plt.subplots(figsize = (10,7))
    x,y = convert_tot(dXY)
    couleurs = convert_tot_coul(dcouleurs)
    plt.scatter(x, y, d, c=couleurs, alpha=transpg)
    if etiquettes==True:
        for c in dadj :
            ax.annotate(c, dXY[c], size = 15, va="center", ha="center")
    for c in dadj:
        for j in dadj[c]:
            X = [dXY[c][0],dXY[j][0]]
            Y = [dXY[c][1],dXY[j][1]]
            if dcouleurs[c] == JAUNE or dcouleurs[j] == JAUNE :
                coul,transpa = JAUNE,1
            elif dcouleurs[c] == BLEU or dcouleurs[j] == BLEU :
                coul,transpa = BLEU,0.2
            else :
                coul,transpa = ROUGE,0.4
            ax.plot(X, Y, color=coul, alpha = transpa)
    plt.show()
