/// <summary>
 /// expected input is { nodes, edges} object
 /// </summary>
 /// <param name="sigmaGraphJson"></param>
 /// <returns></returns>
 public RedBlackTree JsonToTree(string sigmaGraphJson)
 {
     try
     {
         SigmaGraph graph = new SigmaGraph(sigmaGraphJson);
         return(ConvertToTree(graph));
     }
     catch (Exception ex)
     {
         Debug.WriteLine(ex.ToString());
         throw ex;
     }
 }
        public string ToSigmaJson(ITree tree)
        {
            //format specified for sigma.js graph

            SigmaGraph sigma    = ConvertToSigmaGraph(tree);
            var        settings = new JsonSerializerSettings {
                NullValueHandling = NullValueHandling.Ignore
            };
            string json = JsonConvert.SerializeObject(sigma,
                                                      Newtonsoft.Json.Formatting.None, settings);

            return(json);
        }
        public SigmaGraph ConvertToSigmaGraph(ITree tree)
        {
            var graph = new SigmaGraph();

            if (tree.Root == null)
            {
                throw new ArgumentNullException();
            }
            if (tree.Root.Value == null)
            {
                return(graph);
            }

            int h = tree.GetTreeHeight();
            //width of tree on lowest level is 2^(h-1)*2-1
            int w = (int)Math.Pow(2, h) - 1;

            //incremented after every dequeued node, used to calculate current tree level
            int nodeCounter = 0;
            int level       = 0;

            int margin    = 0;
            int separator = 0;

            //traverse tree with queue
            Queue <Node> queue = new Queue <Node>();

            queue.Enqueue(tree.Root);

            while (queue.Count != 0)
            {
                if (nodeCounter >= Math.Pow(2, level))
                {
                    nodeCounter = 0;
                    level++;
                }

                margin    = (int)Math.Pow(2, h - level - 1) - 1;
                separator = (int)Math.Pow(2, h - level) - 1;

                int x = margin + (separator + 1) * (nodeCounter) + 1;

                var node = queue.Dequeue();
                nodeCounter++;

                queue.Enqueue(node.Left);
                queue.Enqueue(node.Right);

                if (node.Value == null)
                {
                    continue;
                }

                var snode = new SigmaNode(node, x, level * h);
                graph.nodes.Add(snode);

                if (node.Left.Value != null)
                {
                    graph.edges.Add(new SigmaEdge(node.id.ToString(), node.Left.id.ToString()));
                }

                if (node.Right.Value != null)
                {
                    graph.edges.Add(new SigmaEdge(node.id.ToString(), node.Right.id.ToString()));
                }

                if (queue.All(n => n.Value == null))
                {
                    break;
                }
            }
            return(graph);
        }
        public RedBlackTree ConvertToTree(SigmaGraph graph)
        {
            var          edgesCopy = new List <SigmaEdge>(graph.edges);
            RedBlackTree newTree   = new RedBlackTree();

            if (graph.nodes.Count == 0)
            {
                return(newTree);
            }

            graph.nodes.OrderBy(x => x.id);

            var addedNodes = new List <Node>();

            foreach (var edge in graph.edges)
            {
                var sourceNode = graph.nodes.FirstOrDefault(x => x.id == edge.source);
                var targetNode = graph.nodes.FirstOrDefault(x => x.id == edge.target);


                if (sourceNode != null && targetNode != null)
                {
                    Node nodeS = FindOrCreateNode(sourceNode);
                    Node nodeT = FindOrCreateNode(targetNode);

                    if (targetNode.isRight)
                    {
                        nodeS.Right = nodeT;
                    }
                    else
                    {
                        nodeS.Left = nodeT;
                    }

                    nodeT.Parent = nodeS;
                }
            }
            //if there were no edges, only root remained in copy collection
            if (!addedNodes.Any())
            {
                FindOrCreateNode(graph.nodes.First());
            }
            //root is only node with sentinel valued parent
            newTree.Root = addedNodes.First(x => x.Parent.Value == null);
            return(newTree);

            Node FindOrCreateNode(SigmaNode sigmaNode)
            {
                if (addedNodes.Any(x => x.id.ToString() == sigmaNode.id))
                {
                    return(addedNodes.First(x => x.id.ToString() == sigmaNode.id));
                }
                else
                {
                    int val;
                    Int32.TryParse(sigmaNode.label, out val);

                    Node newNode = newTree.CreateNode(val);
                    newNode.Color = SigmaNode.SigmaColorToNodeColor(sigmaNode.color);
                    //change to tryparse
                    newNode.id = Int32.Parse(sigmaNode.id);
                    addedNodes.Add(newNode);
                    return(newNode);
                }
            }
        }