using System;
using System.Collections.Generic;
using System.Linq;

namespace Assets.Map
{
    [Serializable]
    public class Graph<T>
    {
        public List<T> Vertices { get; internal set; } = new List<T>();
        public Dictionary<int, List<int>> _edges = new Dictionary<int, List<int>>();

        public T this[int i] => Vertices[i];
        
        public IEnumerable<(int, int)> Edges
        {
            get
            {
                return _edges.SelectMany(pair => pair.Value.Where(value => value > pair.Key).Select(value => (pair.Key, value)));
            }

            set
            {
                _edges = new Dictionary<int, List<int>>();
                
                foreach (var (a, b) in value)
                    AddEdge(a, b);
            }
        }

        public void AddEdge(int a, int b)
        {
            if (!_edges.ContainsKey(a))
                _edges[a] = new List<int>();
            
            if (!_edges.ContainsKey(b))
                _edges[b] = new List<int>();
            
            _edges[a].Add(b);
            _edges[b].Add(a);
        }

        public Graph<U> Morph<U>(Func<T, U> morph)
        {
            var result = new Graph<U>() { Edges = Edges };
            
            result.Vertices.AddRange(Vertices.Select(morph));

            return result;
        }

        public IEnumerable<int> Neighbours(int vertex)
        {
            if (!_edges.ContainsKey(vertex)) return Enumerable.Empty<int>();

            return _edges[vertex];
        }
    }
}