using SimpleCore;
using System.Collections.Generic;

namespace StandardScene.Magnetic.Tasking
{
    internal static class Fass2PathFinder
    {
        public static List<int> GetSitesBetweenBfs(int startSiteId, int endSiteId)
        {
            if (startSiteId == endSiteId)
            {
                return new List<int> { startSiteId };
            }

            var adjacency = BuildSiteAdjacency();
            var visited = new HashSet<int> { startSiteId };
            var queue = new Queue<List<int>>();
            queue.Enqueue(new List<int> { startSiteId });

            while (queue.Count > 0)
            {
                var path = queue.Dequeue();
                var current = path[path.Count - 1];
                if (current == endSiteId)
                {
                    return path;
                }

                if (!adjacency.TryGetValue(current, out var neighbors))
                {
                    continue;
                }

                foreach (var neighbor in neighbors)
                {
                    if (visited.Contains(neighbor))
                    {
                        continue;
                    }

                    visited.Add(neighbor);
                    var nextPath = new List<int>(path) { neighbor };
                    queue.Enqueue(nextPath);
                }
            }

            return new List<int>();
        }

        private static Dictionary<int, HashSet<int>> BuildSiteAdjacency()
        {
            var adjacency = new Dictionary<int, HashSet<int>>();
            foreach (var track in SimpleLib.GetAllTracks())
            {
                var siteA = track.siteA;
                var siteB = track.siteB;
                switch (track.direction)
                {
                    case 0:
                        AddAdjacency(adjacency, siteA, siteB);
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                    case 1:
                        AddAdjacency(adjacency, siteA, siteB);
                        break;
                    case 2:
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                    default:
                        AddAdjacency(adjacency, siteA, siteB);
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                }
            }

            return adjacency;
        }

        private static void AddAdjacency(Dictionary<int, HashSet<int>> adjacency, int from, int to)
        {
            if (!adjacency.TryGetValue(from, out var set))
            {
                set = new HashSet<int>();
                adjacency[from] = set;
            }

            set.Add(to);
        }
    }
}
