
connections = [('Würzburg', 'Schweinfurt', 50),
             ('Würzburg', 'Nürnberg', 100),
             ('Schweinfurt', 'Bamberg', 60),
             ('Bamberg', 'Coburg', 50),
             ('Bamberg', 'Nürnberg', 60),
             ('Bamberg', 'Bayreuth', 60),
             ('Nürnberg', 'Bayreuth', 90),
             ('Bayreuth', 'Hof', 50),
             ('Coburg', 'Hof', 80),
            ]

def allNodes(connections):
    nodes = set()

    for a in connections:
        nodes.add(a[0])
        nodes.add(a[1])
    
    return nodes

def initMap(connections):

    m = allNodes(connections)
    knoten = {}
    
    for a in m:
        knoten[a] = {}
    
    return knoten

def addConnection(data, connection):
    a, b, c = connection

    data[a].setdefault('connection', []).append([b, c])
    data[b].setdefault('connection', []).append([a, c])

    return data

def resetMap(map):
    for node in map:
        map[node]["distance"] = None
        map[node]["predecessor"] = None
        map[node]["finalized"] = False

def setStart(map, start):
    resetMap(map)
    map[start]["distance"] = 0
    map[start]["predecessor"] = start
    map[start]["finalized"] = False

    return map


def calculateAllDistances(map: dict):


    while True:
        knoten = None
        dist = None

        for stadt in map:
            if map[stadt]["finalized"] == False and map[stadt]["distance"] is not None:
                if dist is None or map[stadt]["distance"] < dist:
                    knoten = stadt
                    dist = map[stadt]["distance"]

        if knoten == None:
            break
        
        map[knoten]["finalized"] = True

        for verbindung in map[knoten]["connection"]:
            zielstadt = verbindung[0]
            entfernung = verbindung[1]

            neue_entfernung = map[knoten]["distance"] + entfernung

            if map[zielstadt]["distance"] is None or neue_entfernung < map[zielstadt]["distance"]:
                map[zielstadt]["distance"] = neue_entfernung
                map[zielstadt]["predecessor"] = knoten

    return map

        
def pathFromTo(map, start, ende):
    path = []

    aktuelle_stadt = ende

    while True:
        path.insert(0, aktuelle_stadt)

        if aktuelle_stadt == start:
            break

        aktuelle_stadt = map[aktuelle_stadt]["predecessor"]

    return path


    
map = initMap(connections)
# print(initMap(connections))
# print(connections[0][0])
for con in connections:
    addConnection(map, con)
# print(map)
setStart(map, "Würzburg")
calculateAllDistances(map)
print(calculateAllDistances(map))
print(pathFromTo(map, "Würzburg", "Hof"))
