namespace MathModEduPr02
{
    internal class Program
    {
        const string file1 = @"..\..\..\..\jonson\1.txt";
        const string file2 = @"..\..\..\..\jonson\2.txt";
        const string file3= @"..\..\..\..\jonson\3.txt";

        const string fileOut1 = @"..\..\..\..\jonson\out1.txt";
        const string fileOut2 = @"..\..\..\..\jonson\out2.txt";
        const string fileOut3 = @"..\..\..\..\jonson\out3.txt";
        static List<(int,int)> PairListFromFile(string path)
        {
            List<string> lines = File.ReadAllLines(path).ToList();
            List<(int, int)> newData = new List<(int, int)>();
            foreach (string line in lines)
            {
                int[] curArr = line.Split(' ').Select(int.Parse).ToArray();
                newData.Add((curArr[0], curArr[1]));
            }
            return newData;
        }
        static JohnsonsAlg ReadJonsonAlgFromFile(string path) => new JohnsonsAlg(PairListFromFile(path));
        static Graph ReadTreeEdgesFromFile(string path) => new Graph(PairListFromFile(path));

        const string filePrCode1 = @"..\..\..\..\preuferCode\1.txt",
                     filePrCode2 = @"..\..\..\..\preuferCode\2.txt";

        const string filePrCodeOut1 = @"..\..\..\..\preuferCode\out1.txt",        
                     filePrCodeOut2 = @"..\..\..\..\preuferCode\out2.txt";
        static string WritePairList(List<(int,int)> list)
        {
            string results = "";
            foreach(var pair in list)
            {
                results += $"{pair.Item1} {pair.Item2}\n";
            }
            return results;
        }
        static void WriteJonsonAlgRoFile(string path, JohnsonsAlg alg)
        {
            string results = "new scheme:\n";
            results += WritePairList(alg.NewScheme);
            results += $"\nfirst res: {alg.OldResult}, last res: {alg.NewResult} -> difference: {alg.ResultDiff}";
            File.WriteAllText(path, results);
        }
        static void WritePrufferCodeToFile(string path, List<int> preufferCode)
        {
            string result = "Preuffer code:\n";
            foreach (int vertex in preufferCode)
                result += $"{vertex} ";
            File.WriteAllText(path, result);
        }
        static void WriteGraphToFile(string path, Graph graph)
        {
            string results = "graph:\n";
            results += WritePairList(graph.Edges);
            File.WriteAllText(path, results);
        }
        const string filePrDecoding1 = @"..\..\..\..\preuferDecoding\1.txt",
                     filePrDecoding2 = @"..\..\..\..\preuferDecoding\2.txt";

        const string filePrDecodingOut1 = @"..\..\..\..\preuferDecoding\out1.txt",
                     filePrDecodingOut2 = @"..\..\..\..\preuferDecoding\out2.txt";

        const string fileInvestment = @"..\..\..\..\investment\1.txt",
                     filrInvestmentOut = @"..\..\..\..\investment\out1.txt";
        static List<List<double>> DoubleListFromFile(string path) => File.ReadAllLines(path).ToList().Select(x => x.Split(" ").Select(Double.Parse).ToList()).ToList();
        static Investment ReadInvestmentFromFile(string path)
        {
            List<List<double>> values = DoubleListFromFile(path);
            int investmentCount = (int)values[0][0], investmentStep = (int)values[0][1];
            values.RemoveAt(0);
            int banksCount = values[0].Count;
            return new Investment(banksCount, investmentCount, investmentStep, values);
        }
        static void WriteInvestmentDistribution(string path, Investment investment)
        {
            string result = $"Total income: {investment.TotalIncome}\n";
            for (int i = 0; i < investment.Distribution.Count; i++)
                result += $"{i + 1} bank: {investment.Distribution[i]}\n";
            File.WriteAllText(path, result);
        }
        static void Main(string[] args)
        {
            //Задача Джонсона
            JohnsonsAlg alg1 = ReadJonsonAlgFromFile(file1);
            alg1.Solve();
            WriteJonsonAlgRoFile(fileOut1, alg1);

            JohnsonsAlg alg2 = ReadJonsonAlgFromFile(file2);
            alg2.Solve();
            WriteJonsonAlgRoFile(fileOut2, alg2);

            JohnsonsAlg alg3 = ReadJonsonAlgFromFile(file3);
            alg3.Solve();
            WriteJonsonAlgRoFile(fileOut3, alg3);

            //Код Прюфера
            Graph graph1 = ReadTreeEdgesFromFile(filePrCode1);
            List<int> prCode1 = graph1.PreufferEncoding();
            WritePrufferCodeToFile(filePrCodeOut1, prCode1);            
            
            Graph graph2 = ReadTreeEdgesFromFile(filePrCode2);
            List<int> prCode2 = graph2.PreufferEncoding();
            WritePrufferCodeToFile(filePrCodeOut2, prCode2);

            //Декодирование Прюфера
            Graph graph3 = new Graph(File.ReadAllText(filePrDecoding1));
            WriteGraphToFile(filePrDecodingOut1, graph3);            
            
            Graph graph4 = new Graph(File.ReadAllText(filePrDecoding2));
            WriteGraphToFile(filePrDecodingOut2, graph4);

            //Задача Монте-Карло
            double Pi1 = Monte_CarloProblem.FindPi();
            Console.WriteLine("Пи 1:\t" + Pi1);

            double Pi2 = Monte_CarloProblem.FindPi(1, 1000000, 0.001);
            Console.WriteLine("Пи 2\t" + Pi2);

            Monte_CarloProblem.funtions f1 =
                (double x, double y, ref bool pre) => pre &= x / 3.0 < y;
            f1 += (double x, double y, ref bool pre) => pre &= y < x * (10.0 - x) / 5.0;
            double S1 = Monte_CarloProblem.FindAreaOfShape(8.3, 5.0, f1);
            Console.WriteLine("Пример:\t" + S1);

            Monte_CarloProblem.funtions f2 =
                (double x, double y, ref bool pre) => pre &= y < Math.Sin(x);
            f1 += (double x, double y, ref bool pre) => pre &= y > 0.0;
            double S2 = Monte_CarloProblem.FindAreaOfShape(20.0, 1.0, f2, -5.0);
            Console.WriteLine("1:\t" + S2);

            Monte_CarloProblem.funtions f3 =
                (double x, double y, ref bool pre) => pre &= y < x * (8.0 - x) / 2.0;
            f3 += (double x, double y, ref bool pre) => pre &= y > x / 2.0;
            double S3 = Monte_CarloProblem.FindAreaOfShape(7.0, 8.0, f3);
            Console.WriteLine("2:\t" + S3);

            Monte_CarloProblem.funtions f4 =
                (double x, double y, ref bool pre) => pre &= y < 6.0;
            f4 += (double x, double y, ref bool pre) => pre &= y > Math.Pow(x - 6.0, 2.0) / 6.0;
            double S4 = Monte_CarloProblem.FindAreaOfShape(12.0, 6.0, f4);
            Console.WriteLine("3:\t" + S4);

            Monte_CarloProblem.funtions f5 =
                (double x, double y, ref bool pre) => pre &= y < x * (12.0 - x) / 9.0;
            f5 += (double x, double y, ref bool pre) => pre &= y > x / 5.0;
            double S5 = Monte_CarloProblem.FindAreaOfShape(10.2, 4.0, f5);
            Console.WriteLine("4:\t" + S5);

            Monte_CarloProblem.funtions f6 =
                (double x, double y, ref bool pre) => pre &= y < x * (8.0 - x) / 4.0;
            f6 += (double x, double y, ref bool pre) => pre &= y > (8.0 - x) / 8.0;
            double S6 = Monte_CarloProblem.FindAreaOfShape(8.0, 4.0, f6);
            Console.WriteLine("5:\t" + S6);

            Monte_CarloProblem.funtions f7 =
                (double x, double y, ref bool pre) => pre &= y < Math.Sin(x);
            f7 += (double x, double y, ref bool pre) => pre &= y > Math.Pow(x - 2.0, 2.0) / 2.0;
            double S7 = Monte_CarloProblem.FindAreaOfShape(2.01, 1, f7, 0.8);
            Console.WriteLine("6:\t" + S7);

            //Распределение инвестиций
            Investment investment1 = ReadInvestmentFromFile(fileInvestment);
            investment1.Distribute();
            WriteInvestmentDistribution(filrInvestmentOut, investment1);
        }
    }
}