package com.zivilon.cinder_loe.carriage;

import cpw.mods.fml.common.FMLLog;
import org.apache.logging.log4j.Level;

import java.util.*;

public class CarriageRoadRegistry {
    public static final CarriageRoadRegistry INSTANCE = new CarriageRoadRegistry();
    private static final Map<String, CarriageRoad> roads = new HashMap<>();

    public static void init() {
        FMLLog.log(Level.INFO, "[CinderLoE] Initializing carriage road registry…");
        FMLLog.log(Level.INFO, "[CinderLoE] Registered %d roads", roads.size());
        // create roads
        for (String id : Arrays.asList(
                "sea",
                // North West
                "shire","bree","tharbad","fornost","lonelands",
                "towerhills","mithlond","bluedwarf",
                "longdaer", "eregion", "enedwaith",
                // Vales of Anduin
                "anduin", "lothlorien", "dolguldur", "greenwood", "mirkwood", "brownlands", "greymountain",
                // The East
                "erebor", "dale", "ironhills", "wilderland", "rhun", "rhudel", "dorwinion",
                //Mordor
                "gorgoroth", "sauronsroad", "morgulvale", "nurn", "eastdesolation",
                //Centerlands
                "isen", "rohan", "wold", "anorien","ithilien", "lebennin", "dolamroth", "lamedon",
                //Harad
                "harondor", "khand", "harnennor", "southron", "umbar", "southgulf", "northgulf",
                //Far Harad
                "southjungle", "taurelonde", "centerjungle", "northjungle", "mangrove", "halftroll"

        )) {
            roads.put(id, new CarriageRoad(id));
        }

        // link neighbors
        // North West
        roads.get("shire").neighbors.addAll(Arrays.asList(
                roads.get("bree"),
                roads.get("towerhills"))
        );
        roads.get("enedwaith").neighbors.addAll(Arrays.asList(
                roads.get("tharbad"),
                roads.get("isen"))
        );
        roads.get("bree").neighbors.addAll(Arrays.asList(
                roads.get("shire"),
                roads.get("lonelands"),
                roads.get("fornost"),
                roads.get("tharbad"))
        );
        roads.get("lonelands").neighbors.addAll(Arrays.asList(
                roads.get("bree"),
                roads.get("anduin"))
        );
        roads.get("fornost").neighbors.add(
                roads.get("bree")
        );
        roads.get("tharbad").neighbors.addAll(Arrays.asList(
                roads.get("bree"),
                roads.get("longdaer"),
                roads.get("eregion"),
                roads.get("enedwaith"))
        );
        roads.get("towerhills").neighbors.add(
                roads.get("mithlond")
        );
        roads.get("mithlond").neighbors.addAll(Arrays.asList(
                roads.get("towerhills"),
                roads.get("bluedwarf"))
        );
        roads.get("bluedwarf").neighbors.add(
                roads.get("mithlond")
        );
        //Vales of Anduin
        roads.get("anduin").neighbors.addAll(Arrays.asList(
                roads.get("lonelands"),
                roads.get("greymountain"),
                roads.get("brownlands"),
                roads.get("dolguldur"))
        );
        roads.get("mirkwood").neighbors.addAll(Arrays.asList(
                roads.get("anduin"),
                roads.get("dale"))
        );
        roads.get("greenwood").neighbors.add(
                roads.get("anduin")
        );
        roads.get("dolguldur").neighbors.addAll(Arrays.asList(
                roads.get("brownlands"),
                roads.get("anduin"))
        );
        roads.get("brownlands").neighbors.addAll(Arrays.asList(
                roads.get("gorgoroth"),
                roads.get("anduin"),
                roads.get("wilderland"),
                roads.get("ithilien"),
                roads.get("dolguldur"))
        );
        roads.get("greymountain").neighbors.add(
                roads.get("anduin")
        );
        // The East
        roads.get("dale").neighbors.addAll(Arrays.asList(
                roads.get("erebor"),
                roads.get("ironhills"),
                roads.get("wilderland"),
                roads.get("rhun"))
        );
        roads.get("rhudel").neighbors.addAll(Arrays.asList(
                roads.get("dorwinion"),
                roads.get("sauronsroad"),
                roads.get("rhun"))
        );
        roads.get("rhun").neighbors.addAll(Arrays.asList(
                roads.get("dale"),
                roads.get("rhudel"))
        );
        roads.get("dorwinion").neighbors.addAll(Arrays.asList(
                roads.get("wilderland"),
                roads.get("rhudel"))
        );
        roads.get("wilderland").neighbors.addAll(Arrays.asList(
                roads.get("brownlands"),
                roads.get("dorwinion"),
                roads.get("dale"))
        );
        roads.get("erebor").neighbors.add(
                roads.get("dale")
        );
        roads.get("ironhills").neighbors.add(
                roads.get("dale")
        );
        //Mordor
        roads.get("sauronsroad").neighbors.addAll(Arrays.asList(
                roads.get("brownlands"),
                roads.get("rhudel"),
                roads.get("khand"),
                roads.get("ithilien"),
                roads.get("gorgoroth"))
        );
        roads.get("gorgoroth").neighbors.addAll(Arrays.asList(
                roads.get("brownlands"),
                roads.get("sauronsroad"),
                roads.get("morgulvale"),
                roads.get("nurn"))
        );
        roads.get("morgulvale").neighbors.addAll(Arrays.asList(
                roads.get("ithilien"),
                roads.get("gorgoroth"))
        );
        roads.get("nurn").neighbors.add(
                roads.get("gorgoroth")
        );
        //Centerlands
        roads.get("anorien").neighbors.addAll(Arrays.asList(
                roads.get("rohan"),
                roads.get("lebennin"),
                roads.get("ithilien"))
        );
        roads.get("lebennin").neighbors.addAll(Arrays.asList(
                roads.get("anorien"),
                roads.get("dolamroth"),
                roads.get("lamedon"),
                roads.get("ithilien"))
        );
        roads.get("dolamroth").neighbors.add(
                roads.get("lebennin")
        );
        roads.get("lamedon").neighbors.add(
                roads.get("lebennin")
        );
        roads.get("rohan").neighbors.addAll(Arrays.asList(
                roads.get("wold"),
                roads.get("anorien"),
                roads.get("isen"))
        );
        roads.get("wold").neighbors.add(
                roads.get("rohan")
        );
        roads.get("isen").neighbors.addAll(Arrays.asList(
                roads.get("enedwaith"),
                roads.get("rohan"))
        );

        roads.get("ithilien").neighbors.addAll(Arrays.asList(
                roads.get("anorien"),
                roads.get("lebennin"),
                roads.get("harondor"),
                roads.get("sauronsroad"),
                roads.get("morgulvale"))
        );
        //Harad
        roads.get("northgulf").neighbors.add(
                roads.get("southgulf")
        );
        roads.get("southgulf").neighbors.add(
                roads.get("northgulf")
        );
        roads.get("southron").neighbors.add(
                roads.get("umbar")
        );
        roads.get("umbar").neighbors.addAll(Arrays.asList(
                roads.get("harnennor"),
                roads.get("southron"))
        );
        roads.get("harnennor").neighbors.addAll(Arrays.asList(
                roads.get("harondor"),
                roads.get("khand"),
                roads.get("umbar"))
        );
        roads.get("harondor").neighbors.addAll(Arrays.asList(
                roads.get("harnennor"),
                roads.get("ithilien"))
        );
        roads.get("khand").neighbors.addAll(Arrays.asList(
                roads.get("harnennor"),
                roads.get("sauronsroad"))
        );
        //Far Harad
        roads.get("centerjungle").neighbors.addAll(Arrays.asList(
                roads.get("southjungle"),
                roads.get("northjungle"),
                roads.get("mangrove"),
                roads.get("taurelonde"),
                roads.get("halftroll"))
        );
        roads.get("taurelonde").neighbors.addAll(Arrays.asList(
                roads.get("centerjungle"),
                roads.get("northjungle"))
        );
        roads.get("northjungle").neighbors.addAll(Arrays.asList(
                roads.get("mangrove"),
                roads.get("centerjungle"),
                roads.get("taurelonde"),
                roads.get("halftroll"))
        );
        roads.get("mangrove").neighbors.addAll(Arrays.asList(
                roads.get("northjungle"),
                roads.get("centerjungle"),
                roads.get("halftroll"))
        );
        roads.get("halftroll").neighbors.addAll(Arrays.asList(
                roads.get("northjungle"),
                roads.get("centerjungle"),
                roads.get("mangrove"))
        );
        roads.get("southjungle").neighbors.add(
                roads.get("centerjungle")
        );

    }
    public static CarriageRoad getRoad(String name) {
        return roads.get(name);
    }

    public static Collection<CarriageRoad> allRoads() {
        return roads.values();
    }

    public static Set<String> reachableRoadIds(String startRoadId) {
        Set<String> seen = new HashSet<>();
        Deque<String> queue = new ArrayDeque<>();
        queue.add(startRoadId);
        seen.add(startRoadId);

        while (!queue.isEmpty()) {
            String current = queue.removeFirst();
            CarriageRoad road = CarriageRoadRegistry.getRoad(current);
            if (road == null) continue;
            for (CarriageRoad nbr : road.neighbors) {
                if (seen.add(nbr.name)) {
                    queue.addLast(nbr.name);
                }
            }
        }

        return seen;
    }

}
