namespace Noctalk_client.Splash_screen;

public sealed class RouteGenerator
{
    private readonly Random random = new(Guid.NewGuid().GetHashCode());
    private readonly IReadOnlyList<RouteNode> nodes = WorldMapNodeProvider.Nodes__get();

    public List<RouteNode> Route__generate()
    {
        List<RouteNode> route = [];
        List<RouteRegion> selectedRegions = Enum.GetValues<RouteRegion>()
            .OrderBy(_ => random.Next())
            .Take(5)
            .ToList();

        RouteNode current = Route__random_node_from_region__pick(selectedRegions[0]).Clone_for_route();
        route.Add(current);

        for (int index = 1; index < selectedRegions.Count; index++)
        {
            current = Route__next_node__pick(current, selectedRegions[index], route).Clone_for_route();
            route.Add(current);
        }

        route[route.Count - 3].Flag__rendezvous = true;
        return route;
    }

    private RouteNode Route__random_node_from_region__pick(RouteRegion The_region)
    {
        List<RouteNode> candidates = nodes.Where(The_node => The_node.Region == The_region).ToList();
        return candidates[random.Next(candidates.Count)];
    }

    private RouteNode Route__next_node__pick(RouteNode Current_node, RouteRegion The_region, List<RouteNode> Visited_nodes)
    {
        List<RouteNode> candidates = nodes
            .Where(The_node => The_node.Region == The_region && Visited_nodes.All(The_visited_node => The_visited_node.Name != The_node.Name))
            .OrderByDescending(The_node => Route__distance__score(Current_node, The_node) + random.NextDouble() * 0.18)
            .Take(20)
            .ToList();

        int weightedIndex = Math.Min(candidates.Count - 1, (int)Math.Pow(random.NextDouble(), 1.8) * candidates.Count);
        return candidates[weightedIndex];
    }

    private static double Route__distance__score(RouteNode A, RouteNode B)
    {
        double dx = A.X - B.X;
        double dy = A.Y - B.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }
}
