﻿namespace Microsoft.DAML.GraphEngine.Core.Structure
{
    using System;
    using System.Collections.Generic;
    using Microsoft.DAML.GraphEngine.Core.DataModel;

    /// <summary>
    /// single linked list, which links the vertices together
    /// </summary>
    public sealed class Node : IEquatable<Node>
    {
        private IVertex vertex;
        private IEdge edge;

        public Node(IVertex vertex)
        {
            this.vertex = vertex;
            this.edge = null;
        }

        public Node(IVertex vertex, IEdge edge)
            : this(vertex)
        {
            this.edge = edge;
        }

        public IVertex Vertex
        {
            get;
        }

        public IEdge Edge
        {
            get;
        }

        public bool Equals(Node other)
        {
            if (other == null)
            {
                return false;
            }

            return this.vertex.Equals(other.vertex);
        }

        public override bool Equals(object obj)
        {
            var singleLinkedVertex = obj as Node;
            if (singleLinkedVertex == null)
            {
                return false;
            }

            return this.Equals(singleLinkedVertex);
        }

        public override int GetHashCode()
        {
            return this.vertex.GetHashCode();
        }
    }

    /// <summary>
    /// the underlying data structure storing the graph
    /// </summary>
    public sealed class SingleLinkedVertexStore : IGraph
    {
        private readonly Dictionary<Node, List<Node>> data;

        public SingleLinkedVertexStore()
        {
            data = new Dictionary<Node, List<Node>>();
        }

        public void AddEdge(IEdge edge)
        {
            var source = new Node(edge.Source);
            if (!data.ContainsKey(source))
            {
                data.Add(source, new List<Node>());
            }

            var target = new Node(edge.Target);
            data[source].Add(target);
        }

        public void AddVertex(IVertex vertex)
        {
            var singleLinkedVertex = new Node(vertex);
            if (!data.ContainsKey(singleLinkedVertex))
            {
                data.Add(singleLinkedVertex, new List<Node>());
            }
        }
    }
}
