using MathNet.Numerics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrequentialAucVerifier
{
    public class PrequentialAucVerifier
    {
        public const int aucA = 0;
        public const int prequentialAucA = 1;
        public const int blockAucA = 2;
        public const int aucB = 3;
        public const int prequentialAucB = 4;
        public const int blockAucB = 5;

        static void Main(string[] args)
        {
            int minStreamSize = int.Parse(args[0]);
            int maxStreamSize = int.Parse(args[1]);
            int minWindowSize = int.Parse(args[2]);
            int maxWindowSize = int.Parse(args[3]);
            double majorityClassPercentage = double.Parse(args[4]);

            Stopwatch timer = new Stopwatch();
            timer.Start();

            for (int streamSize = minStreamSize; streamSize <= maxStreamSize; streamSize += 2)
            {
                //// Rozmiar okna
                Parallel.For(minWindowSize, Math.Min(maxWindowSize + 1, streamSize), windowSize =>
                //for (int windowSize = 2; windowSize < streamSize; windowSize++)
                {
                    ScoredExample[] window = new ScoredExample[windowSize];
                    ScoredExample[] ranking = ScoredExample.CreatePermutationArray(streamSize, majorityClassPercentage);
                    ScoredExample[] alternativeRanking = new ScoredExample[streamSize];

                    double[] results = new double[6];
                    Dictionary<double[], long> resultCompressor = new Dictionary<double[], long>(new DoubleArrayComparer());

                    string resultString = string.Empty;
                    byte orderNum = 0;

                    using (StreamWriter file = new StreamWriter(new FileStream("results_i" + (int)Math.Round(majorityClassPercentage * 100) + "_n" + streamSize.ToString("D2") + "_d" + windowSize.ToString("D2"), FileMode.Create)))
                    {
                        file.WriteLine("AUC(a),prequentialAUC(a),blockAUC(a),AUC(b),prequentialAUC(b),blockAUC(b)");

                        //// Ranking(a)
                        do
                        {
                            results[aucA] = ScoredExample.CalculateAUC(ranking);
                            orderNum = 0;

                            // kolejność przykładów w strumieniu
                            do
                            {
                                orderNum++;
                                ranking.CopyTo(alternativeRanking, 0);

                                results[prequentialAucA] = ScoredExample.CalculatePrequentialAUC(ranking, window);
                                results[blockAucA] = ScoredExample.CalculateBlockAUC(ranking, window);

                                //// Ranking(b)
                                do
                                {
                                    results[aucB] = ScoredExample.CalculateAUC(alternativeRanking);

                                    results[prequentialAucB] = ScoredExample.CalculatePrequentialAUC(alternativeRanking, window);
                                    results[blockAucB] = ScoredExample.CalculateBlockAUC(alternativeRanking, window);

                                    //resultString = string.Join(",", aucA, prequentialAucA, blockAucA, aucB, prequentialAucB, blockAucB);
                                    if (resultCompressor.ContainsKey(results))
                                    {
                                        resultCompressor[results]++;
                                    }
                                    else
                                    {
                                        double[] resultKey = new double[6];
                                        results.CopyTo(resultKey, 0);
                                        resultCompressor.Add(resultKey, 1);
                                    }
                                } while (ScoredExample.PermuteRanking(alternativeRanking, false));
                            } while (ScoredExample.PermuteOrder(ranking));

                            foreach (var kvp in resultCompressor)
                            {
                                file.WriteLine("{0},{1}", string.Join(",", kvp.Key), kvp.Value);
                            }

                            resultCompressor.Clear();

                        } while (ScoredExample.PermuteRanking(ranking, true));
                    }
                }
                );
            }

            Console.WriteLine("Czas przetwarzania: " + timer.Elapsed);
        }
    }
}
