using System;
using System.Collections.Generic;
using System.Text;
using QuickGraph;
using QuickGraph.Algorithms;
using QuickGraph.Serialization;
using System.IO;

using MyVertex = System.Int32;
using MyEdge = QuickGraph.Edge<System.Int32>;
using GRAPH = QuickGraph.AdjacencyGraph<System.Int32, QuickGraph.Edge<System.Int32>>;
//QuickGraph.CompressedSparseRowGraph<System.Int32>;

namespace CSharpTest
{
    class Program
    {
        const string outFile = "output.bin";
        
        static void Main(string[] args)
        {
            GRAPH graph;
            using (Stream stream = File.Open(outFile, FileMode.Open))
            {
               // var gr = stream.DeserializeFromBinary<MyVertex, MyEdge, AdjacencyGraph<MyVertex, MyEdge>>();
                graph = stream.DeserializeFromBinary<MyVertex, MyEdge, AdjacencyGraph<MyVertex, MyEdge>>(); //gr.ToAdjacencyGraph();
            }
            //force JIT comiler to process required functions
            //HasCycles(graph);

            Console.WriteLine("Server collection = {0}", System.Runtime.GCSettings.IsServerGC);
            Console.WriteLine("Press <enter> to begin test");
            Console.ReadLine();
            //start test
            Int64 startTick = DateTime.Now.Ticks;

            bool hasCycles = false;
            //int comp = 0;
            for (int i = 0; i < 100; i++)
            {
               // hasCycles = HasCycles(graph);
                hasCycles = HasCyclesSelf(graph);
               // comp = TestComponents(graph);
            }           
            
            var spanningTime = new TimeSpan(DateTime.Now.Ticks - startTick);

            //Console.WriteLine("{0} components", comp);
            Console.WriteLine(hasCycles ? "Graph has cycles" : "Graph hasn't cycles");
            Console.WriteLine("Computation has taken {0} milliseconds", spanningTime.TotalMilliseconds);           
        }

        static bool HasCycles(GRAPH graph)
        {
            return !graph.IsDirectedAcyclicGraph();
        }

        static bool HasCyclesSelf(GRAPH graph)
        {
            var alg = new SelfAcyclicAlgorithm(graph);
            return alg.HasCycles();
        }

        //static int TestDijkstra(AdjacencyGraph<MyVertex, MyEdge> graph)
        //{
        //    var predecessors = new QuickGraph.Algorithms.Observers.VertexPredecessorRecorderObserver<MyVertex, MyEdge>();

        //    Int64 startTick = DateTime.Now.Ticks;
        //    foreach (var vertex in graph.Vertices)
        //    {
        //        var dijkstra = new QuickGraph.Algorithms.ShortestPath.DijkstraShortestPathAlgorithm<MyVertex, MyEdge>(graph, e => 1);
            
        //        predecessors.Attach(dijkstra);
        //        dijkstra.Compute(vertex);
        //    }
        //    var spanningTime = new TimeSpan(DateTime.Now.Ticks - startTick);
        //    return spanningTime.Milliseconds;
        //}
        /*
        static int TestComponents(GRAPH graph)
        {
            var alg = new QuickGraph.Algorithms.ConnectedComponents.StronglyConnectedComponentsAlgorithm<MyVertex, MyEdge>(graph);
            alg.Compute();
            var compts = alg.Components;
            return alg.ComponentCount;
        }
*/
        //static IEnumerable<MyVertex> TopologicalSort(AdjacencyGraph<MyVertex, MyEdge> graph)
        //{
        //    return graph.TopologicalSort();            
        //}
    }
}
