the following code shows a map with linking lines between each node / town, please make it so that when you select / click a node on the displayed map; each line / connection from the clicked node that can be reached is highlighted

// This program is copyright VUW.
// You are granted permission to use it to construct your answer to a COMP103 assignment.
// You may not distribute it in any other way without permission.

/* Code for COMP103 - 2024T2, Assignment 6
 * Name:
 * Username:
 * ID:
 */

import ecs100.*;

import java.awt.*;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.List;

public class BusNetworks {

    /**
     * Map of towns, indexed by their names
     */
    private Map<String, Town> busNetwork = new HashMap<String, Town>();
    private List<String> townOrder = new ArrayList<>();
    Map<String, Point2D.Double> coords = new HashMap<>();

    //for challenge ; map interaction
    private double scaleFactor = 1.0;      // Current scale factor
    private double offsetX = 0.0;          // Current x-axis offset
    private double offsetY = 0.0;

    private boolean dragging = false;
    private double lastMouseX, lastMouseY;
    /**
     * CORE
     * Loads a network of towns from a file.
     * Constructs a Map of Town objects in the busNetwork field
     * Each town has a name and a set of neighbouring towns
     * First line of file contains the names of all the towns.
     * Remaining lines have pairs of names of towns that are connected.
     */
    public void loadNetwork(String filename) {
        try {
            busNetwork.clear();
            townOrder.clear();
            UI.clearText();
            List<String> lines = Files.readAllLines(Path.of(filename));

            String firstLine = lines.remove(0);
            int start = 0;
            try {
                start = Integer.parseInt(firstLine);
                UI.println("number: " + start);
                for (int i = 0; i < start; i++) {
                    String name = lines.get(i).split(" ")[0].trim();
                    double lat = Double.parseDouble(lines.get(i).split(" ")[1].trim());
                    double lon = Double.parseDouble(lines.get(i).split(" ")[2].trim());

                    busNetwork.put(name, new Town(name));
                    coords.put(name, new Point2D.Double(lat,lon));

                    townOrder.add(name);

                }
            } catch (NumberFormatException e) {    //parsing fails; is string
                UI.println("Loaded file with coordinates");
            }
            List<String> cutLines = lines.subList(start,lines.size());

            if (start == 0) {
                String[] townNames = firstLine.split(" ");
                for (String name : townNames) {
                    busNetwork.put(name, new Town(name));
                    townOrder.add(name);
                }
            }

            // Process the remaining lines to add connections between towns
            for (String line : cutLines) {
                String[] towns = line.split(" ");

                Town town1 = busNetwork.get(towns[0]);
                Town town2 = busNetwork.get(towns[1]);

                if (town1 != null && town2 != null) {
                    town1.addNeighbour(town2);
                    town2.addNeighbour(town1);
                }
            }
            UI.println("Loaded " + busNetwork.size() + " towns:");
        } catch (IOException e) {
            throw new RuntimeException("Loading data.txt failed" + e);
        }
    }


    /**
     * CORE
     * Print all the towns and their neighbours:
     * Each line starts with the name of the town, followed by
     * the names of all its immediate neighbours,
     */
    public void printNetwork() {
        UI.println("The current network: \n====================");
        for (String townName : townOrder) {
            Town town = busNetwork.get(townName);
            StringBuilder sb = new StringBuilder(town.getName() + "-> ");
            List<String> neighborNames = new ArrayList<>();
            for (Town neighbour : town.getNeighbours()) {
                neighborNames.add(neighbour.getName());
            }
            Collections.sort(neighborNames);
            sb.append(String.join(" ", neighborNames));
            UI.println(sb.toString());
        }
    }


    /**
     * COMPLETION
     * Return a set of all the nodes that are connected to the given node.
     * Traver se the network from this node in the standard way, using a
     * visited set, and then return the visited set
     */
    public Set<Town> findAllConnected(Town town) {
        /*# YOUR CODE HERE */
        Set<Town> visited = new HashSet<>();
        findRecur(visited, town);
        return visited;
    }

    public void findRecur(Set<Town> seen, Town town) {
        if (seen.contains(town)) return;
        seen.add(town);
        town.getNeighbours().forEach(t -> findRecur(seen, t));
    }

    //public Set

    /**
     * COMPLETION
     * Print all the towns that are reachable through the network from
     * the town with the given name.
     * Note, do not include the town itself in the list.
     */
    public void printReachable(String name) {
        Town town = busNetwork.get(name);
        if (town == null) {
            UI.println(name + " is not a recognised town");
        } else {
            UI.println("\nFrom " + town.getName() + " you can get to:");
            /*# YOUR CODE HERE */
            Set<Town> reachable = findAllConnected(town);
            reachable.remove(town);
            reachable.forEach(t -> UI.print(t.getName() + " "));
        }

    }

    /**
     * COMPLETION
     * Print all the connected sets of towns in the busNetwork
     * Each line of the output should be the names of the towns in a connected set
     * Works through busNetwork, using findAllConnected on each town that hasn't
     * yet been printed out.
     */
    public void printConnectedGroups() {
        UI.println("Groups of Connected Towns: \n================");
        int groupNum = 1;
        /*# YOUR CODE HERE */
        Set<Town> group = new HashSet<>();
        Set<Town> visited = new HashSet<>(group);
        for (Town town : busNetwork.values()) {
            if (!visited.contains(town)) {
                group.addAll(findAllConnected(town));
                UI.print("\n Group " + groupNum + ": ");
                group.forEach(t -> UI.print(t.getName() + " "));
                groupNum++;
                visited.addAll(group);
                group.clear();
            }
        }
    }

    public void displayGraph(){
        UI.clearGraphics();
        int windowWidth = UI.getCanvasWidth();
        int windowHeight = UI.getCanvasHeight();
        int padding = 10;

        double minLat = Double.MAX_VALUE;
        double maxLat = -Double.MAX_VALUE;
        double minLon = Double.MAX_VALUE;
        double maxLon = -Double.MAX_VALUE;

        for (Point2D.Double point : coords.values()) {
            double lat = point.x;
            double lon = point.y;
            if (lat < minLat) minLat = lat;
            if (lat > maxLat) maxLat = lat;
            if (lon < minLon) minLon = lon;
            if (lon > maxLon) maxLon = lon;
        }

        double latRange = maxLat - minLat;
        double lonRange = maxLon - minLon;

        // scaling based on coord range
        double scaleXData = (windowWidth - 2.0 * padding) / lonRange;
        double scaleYData = (windowHeight - 2.0 * padding) / latRange;

        double dataScale = Math.min(scaleXData, scaleYData);

        //centering map
        double dataOffsetX = (windowWidth - 2.0 * padding - (lonRange * dataScale)) / 2.0;
        double dataOffsetY = (windowHeight - 2.0 * padding - (latRange * dataScale)) / 2.0;

        for (String townName : townOrder) {
            Point2D.Double point = coords.get(townName);
            double lat = point.x;
            double lon = point.y;

            double xScaled = padding + dataOffsetX + (lon - minLon) * dataScale;
            double yScaled = padding + dataOffsetY + (lat - minLat) * dataScale;

            double x = xScaled * scaleFactor + offsetX;
            double y = windowHeight - (yScaled * scaleFactor - offsetY);


            UI.setColor(Color.blue);  //each node / town
            UI.fillOval(x - 3, y - 3, 6, 6);

            UI.setColor(Color.black);
            UI.drawString(townName, x + 5, y - 5); //slight offset to minimise ovrlap
        }

        UI.setColor(Color.gray);
        for (String townName : townOrder) {
            Town town = busNetwork.get(townName);
            Point2D.Double fromPoint = coords.get(townName);
            double fromLat = fromPoint.x;
            double fromLon = fromPoint.y;

            double fromXScaled = padding + dataOffsetX + (fromLon - minLon) * dataScale;
            double fromYScaled = padding + dataOffsetY + (fromLat - minLat) * dataScale;

            double fromX = fromXScaled * scaleFactor + offsetX;
            double fromY = windowHeight - (fromYScaled * scaleFactor - offsetY);

            for (Town neighbor : town.getNeighbours()) {  //only 1st layer, but using findAllConnected(town) here display all which is unintelligible
                Point2D.Double toPoint = coords.get(neighbor.getName());
                double toLat = toPoint.x;
                double toLon = toPoint.y;

                double toXScaled = padding + dataOffsetX + (toLon - minLon) * dataScale;
                double toYScaled = padding + dataOffsetY + (toLat - minLat) * dataScale;

                double toX = toXScaled * scaleFactor + offsetX;
                double toY = windowHeight - (toYScaled * scaleFactor - offsetY); // Invert Y-axis

                //line is between immediate neighbours
                UI.drawLine(fromX, fromY, toX, toY);
            }
        }
    }


    public void handleMouse(String action, double x, double y) {
        switch (action) {
            case "dragged" -> {
                double dx = x - lastMouseX;
                double dy = y - lastMouseY;
                offsetX += dx;
                offsetY += dy;
                lastMouseX = x;
                lastMouseY = y;
                displayGraph();
            }
            case "pressed" -> {
                lastMouseX = x;
                lastMouseY = y;
            }
        }
    }

    private void zoom(double level){
        scaleFactor = level;
        displayGraph();
    }

    /**
     * Set up the GUI (buttons and mouse)
     */
    public void setupGUI() {
        UI.addButton("Load", () -> {
            loadNetwork(UIFileChooser.open());
        });
        UI.addButton("Print Network", this::printNetwork);
        UI.addTextField("Reachable from", this::printReachable);
        UI.addButton("All Connected Groups", this::printConnectedGroups);
        UI.addButton("Display graph", this::displayGraph);
        UI.addButton("Clear", UI::clearText);
        UI.addButton("Quit", UI::quit);
        UI.setMouseMotionListener(this::handleMouse);
        UI.addSlider("zoom", 1, 5, 1, this::zoom);
        UI.setWindowSize(1100, 500);
        UI.setDivider(1.0);


        //loadNetwork("data-small.txt");
    }
    // Main
    public static void main(String[] arguments) {
        BusNetworks bnw = new BusNetworks();
        bnw.setupGUI();
    }
}