using DataClient;
using NLog;
using NLog.Config;
using NLog.Targets;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace test3
{
	class Program
	{
		static bool flag_end_task = true;
		static Logger log = LogManager.GetCurrentClassLogger();
		static void Main(string[] args)
		{
			var dconn = false;
			var conn = false;
			foreach(var arg in args)
      {
				if(int.TryParse(arg, out int a))
        {
					if (a == 1)
						dconn = true;
					if (a == 2)
						conn = true;
        }
      }
			if (dconn)
			{
				var proc = new Process
				{
					StartInfo = new ProcessStartInfo
					{
						FileName = "/usr/bin/umount",
						Arguments = "/archive_rmt/",
						UseShellExecute = false,
						RedirectStandardError = true,
						RedirectStandardOutput = true,
					}
				};
				while (true)
				{
					if (!proc.Start())
					{
						Console.WriteLine("Can't Disconnect.");
						Task.Delay(5000).Wait();
						continue;
					}
					var answer = proc.StandardError.ReadToEnd() + proc.StandardOutput.ReadToEnd();
					if (string.IsNullOrEmpty(answer))
          {
						Console.WriteLine("Disconnect success.");
						break;
					}
					if (answer.Contains("not mounted"))
					{
						Console.WriteLine("Already dosconnect.");
						break;
					}
					break;
				}
			}
			if(conn)
      {
				var proc = new Process
				{
					StartInfo = new ProcessStartInfo
					{
						FileName = "/usr/bin/mount",
						Arguments = "-t nfs 10.10.45.236:/archiv /archive_rmt/",
						UseShellExecute = false,
						RedirectStandardError = true,
						RedirectStandardOutput = true,
					},
				};
				while (true)
				{
					if (!proc.Start())
					{
						Console.WriteLine("Can't Disconnect.");
						Task.Delay(5000).Wait();
						continue;
					}
					var answer = proc.StandardError.ReadToEnd() + proc.StandardOutput.ReadToEnd();
					if (string.IsNullOrEmpty(answer))
					{
						Console.WriteLine("Connect success.");
						break;
					}
					if (answer.Contains("busy or already mounted"))
					{
						Console.WriteLine("Busy dir or already mounted.");
						break;
					}
					break;
				}
			}
		}

		static void Tasks()
    {
			LogConf();
			Test1();
			Console.ReadKey();
			Test2();
			Console.ReadKey();
			Test3();
			Console.ReadKey();
			Test4();
			Console.ReadKey();
			Test5();
			Console.ReadKey();
			var t6 = new Task(() => Test6());
			t6.Start();
			Console.ReadKey();
			flag_end_task = false;
			t6.Wait();
			Console.ReadKey();
			flag_end_task = true;
			var t7 = new Task(() => Test7());
			t7.Start();
			Console.ReadKey();
			flag_end_task = false;
			t7.Wait();
			Console.ReadKey();
		}

		static void LogConf()
		{
			var conf = new LoggingConfiguration();
			var logcon = new ColoredConsoleTarget()
			{
				Name = "logcon",
				Layout = @"${time}|${level:uppercase=true}|${logger}|${message}${when:when=length('${exception}')>0:Inner=|}${exception:format=ToString,StackTrace}"
			};

			conf.AddRule(LogLevel.Trace, LogLevel.Fatal, logcon);
			LogManager.Configuration = conf;
		}
		//Проверка соединения
		static void Test1()
		{
			log.Error("TEST1:");
			var t = new NETClient("10.10.45.152", 1070);
			log.Warn("Проверка соединения:");
			var start = Environment.TickCount64;
			t.Connect();
			if (t.Connected())
				log.Warn("Соединение ОК!");
			else
				log.Warn("Соединение не удалось!");
			t.Close();
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
		}
		//Проверка получения и отправки кода
		static void Test2()
		{
			log.Error("TEST2:");
			var t = new NETClient("10.10.45.152", 1070);
			log.Warn("Проверка отправки и получения кода (время сервера):");
			var start = Environment.TickCount64;
			var buf = t.CreateCode((uint)NETClient.Code.server_time);
			var s = "";
			foreach (var e in buf)
				s += " 0x" + e.ToString("X2");
			log.Warn("Код отправки:" + s);
			t.Connect();
			log.Warn("Отправляем код.");
			if (t.SendBytes(buf))
			{
				log.Warn("Код отправлен.");
				log.Warn("Получаем ответ.");
				buf = t.ReceiveBytes(7);
				if (buf.Length == 7)
				{
					log.Warn("Ответ получен.");
					s = "";
					foreach (var e in buf)
						s += " 0x" + e.ToString("X2");
					log.Warn("Код ответа:" + s);
					log.Warn("Конвертируем ответ.");
					var date = new DateTime(buf[0] | buf[1] << 8, buf[2], buf[3], buf[4], buf[5], buf[6]);
					log.Warn("Время сервера: " + date.ToString("yyyy.MM.dd HH.mm.ss"));
				}
				else
					log.Warn("Ошибка получения данных.");
			}
			else
				log.Warn("Ошибка отправки кода.");
			t.Close();
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
		}
		//Проверка получения списков паспортов
		static void Test3()
		{
			log.Error("TEST3:");
			var t = new NETClient("10.10.45.152", 1070);
			log.Warn("Проверка получения директории 2021");
			var start = Environment.TickCount64; 
			var r = t.Full_Dir_Browse("2021");
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Результат 2021:");
			if (r == null) log.Warn("Ошибка.");
			else foreach (var e in r) log.Warn(e);
			log.Warn("Проверка получения директории 2021/07");
			start = Environment.TickCount64;
			r = t.Full_Dir_Browse("2021/07");
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Результат 2021/07:");
			if (r == null) log.Warn("Ошибка.");
			else foreach (var e in r) log.Warn(e);
			log.Warn("Проверка получения директории 2021/07/07");
			start = Environment.TickCount64;
			r = t.Full_Dir_Browse("2021/07/07");
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Результат 2021/07/07:");
			if (r == null) log.Warn("Ошибка.");
			else foreach (var e in r) log.Warn(e);
			log.Warn("Проверка получения директории 2022/03/12");
			start = Environment.TickCount64;
			r = t.Full_Dir_Browse("2022/03/12");
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Результат 2022/03/12:");
			if (r == null) log.Warn("Ошибка.");
			else foreach (var e in r) log.Warn(e);
		}
		//Проверка загрузки паспорта
		static void Test4()
		{
			log.Error("TEST4:");
			var t = new NETClient("10.10.45.152", 1070);
			log.Warn("Проверка получения паспорта:");
			log.Warn("Запрос паспорта 2021/07/07/17:55:10-8-10-11495.gz");
			var start = Environment.TickCount64;
			var p = t.Full_Pasp_Download("2021/07/07/17:55:10-8-10-11495.gz");
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Полученный код: ");
			var b = p.PaspByte;
			var s = "";
			foreach (var e in b)
				s += " " + e.ToString("X2");
			log.Warn(s);
			log.Warn("Паспорт получен:");
			log.Warn(" Есть данные?: " + p.HasData.ToString());
			if (p.HasData)
			{
				log.Warn("  Номер печи: " + p.numVDP.Value.ToString());
				log.Warn("  Время начала: " + p.dStart.Value.ToString());
				log.Warn("  Время конца: " + p.dEnd.Value.ToString());
				log.Warn(" Есть паспорт?: " + p.hasPasport.ToString());
				if (p.hasPasport)
				{
					log.Warn("  kod_npl: " + p.kod_npl);
					log.Warn("  nplav: " + p.nplav);
					log.Warn("  rm: " + p.rm);
					log.Warn("  splav: " + p.splav);
					log.Warn("  iS: " + p.iS);
					log.Warn("  notd: " + p.notd);
					log.Warn("  vessl: " + p.vessl);
					log.Warn("  diam: " + p.diam);
					log.Warn("  prpl: " + p.prpl);
					log.Warn("  tin: " + p.tin);
					log.Warn("  dzap: " + p.dzap);
					log.Warn("  dlog: " + p.dlog);
					log.Warn("  last: " + p.last);
					log.Warn("  dlper: " + p.dlper);
					log.Warn("  nazn: " + p.nazn);
					log.Warn("  kompl: " + p.kompl);
					log.Warn("  izl: " + p.izl);
					log.Warn("  robm: " + p.robm);
					log.Warn("  rizol: " + p.rizol);
					log.Warn("  dkr: " + p.dkr);
					log.Warn("  nkon: " + p.nkon);
					log.Warn("  pos: " + p.pos);
					log.Warn("  ukaz: " + p.ukaz);
					log.Warn("  zakaz: " + p.zakaz);
					log.Warn("  kat: " + p.kat);
					log.Warn("  pril: " + p.pril);
					log.Warn("  rezerved: " + p.rezerved);
				}
			}
		}
		//Проверка получения технологического цикла
		static void Test5()
		{
			log.Error("TEST5:");
			var t = new NETClient("10.10.45.152", 1070);
			log.Warn("Проверка получения технологического цикла:");
			log.Warn("Запрос цикла печи 10 за 2021.07.07");
			var start = Environment.TickCount64;
			var r = t.Full_Download(new DateTime(2021, 07, 07), 10, 3);
			log.Error("Время выполнения: " + (Environment.TickCount64 - start));
			log.Warn("Получен код:");
			var s = "";
			foreach (var e in r)
				s += " " + e.ToString("X2");
			log.Warn("Конвертирование кода:");
			var tc = ByteConverter.BytesToTechcycles(r);
			foreach(var e in tc)
				log.Warn(e.start.ToString("yyyy.MM.dd HH.mm.ss") + "     " + e.index.Value.ToString("D2"));
		}

		//Проверка количества соединений
		static void Test6()
		{
			var count = 1;
			var flag_drop = true;
			while(flag_drop == true)
			{
				log.Error("Test " + count.ToString() + ":");

				var listTask = new List<Task<(int id, long ticks)>>();
				for (var i = 0; i < count; i++)
					listTask.Add(new Task<(int id, long ticks)>(() => {
						(int id, long ticks) result;
						var t = new NETClient("10.10.45.152", 1070);
						var start = Environment.TickCount64;
						var buf = t.CreateCode((uint)NETClient.Code.server_time);
						t.Connect();
						if (t.SendBytes(buf))
						{
							buf = t.ReceiveBytes(7);
							if (buf.Length == 7)
							{
								result = (i, Environment.TickCount64 - start);
							}
							else
							{
								t.Close();
								throw new Exception("Ops");
							}
						}
						else
						{
							t.Close();
							throw new Exception("Ops");
						}
						t.Close();
						return result;
					}));

				var start = Environment.TickCount64;
				foreach (var e in listTask) e.Start();

				var flag_check = true;
				while(flag_check) {
					flag_check = false;
					for (var i = 0; i < listTask.Count; i++)
						flag_check = flag_check || !listTask[i].IsCompleted;
					if (flag_check) Task.Delay(100).Wait();
				}
				
				var end = Environment.TickCount64 - start;
				var mid_count = 0D;
				for (var i = 0; i < listTask.Count; i++)
				{
					if (!listTask[i].IsCompletedSuccessfully)
					{
						flag_drop = false;
						continue;
					}
					var res = listTask[i].Result;
					if (mid_count == 0) mid_count += res.ticks;
					else mid_count = (mid_count + res.ticks) / 2;
					flag_drop = flag_drop && (res.ticks < (5000));
					log.Warn(res.id.ToString("D3") + " : " + res.ticks.ToString("D4"));
				}
				log.Error("Mid:   " + mid_count.ToString());
				log.Error("Total: " + end.ToString("D4"));

				flag_drop = flag_drop && flag_end_task;
				if (!flag_drop)
					log.Error("Drop Global Task");
				count++;
			}

		}

		//Проверка скорости работы
		static void Test7()
		{
			var count = 1;
			var flag_drop = true;
			while (flag_drop == true)
			{
				log.Error("Test " + count.ToString() + ":");

				var listTask = new List<Task<(int id, long ticks)>>();
				for (var i = 0; i < count; i++)
					listTask.Add(new Task<(int id, long ticks)>(() => {
						var t = new NETClient("10.10.45.152", 1070);
						var start = Environment.TickCount64;
						var r = t.Full_Download(new DateTime(2021, 07, 08), 30, 1);
						if (r.Length == 0)
							return (i, -1);
					  return (i, Environment.TickCount64 - start);
					}));

				var start = Environment.TickCount64;
				foreach (var e in listTask) e.Start();

				var flag_check = true;
				while (flag_check)
				{
					flag_check = false;
					for (var i = 0; i < listTask.Count; i++)
						flag_check = flag_check || !listTask[i].IsCompleted;
					if (flag_check) Task.Delay(100).Wait();
				}

				var end = Environment.TickCount64 - start;
				var mid_count = 0D;
				for (var i = 0; i < listTask.Count; i++)
				{
					if (!listTask[i].IsCompletedSuccessfully)
					{
						flag_drop = false;
						continue;
					}
					var res = listTask[i].Result;
					if (mid_count == 0) mid_count += res.ticks;
					else mid_count = (mid_count + res.ticks) / 2;
					log.Warn(res.id.ToString("D3") + " : " + res.ticks.ToString("D4"));
				}
				log.Error("Mid:   " + mid_count.ToString());
				log.Error("Total: " + end.ToString("D4"));

				flag_drop = flag_drop && flag_end_task;
				if (!flag_drop)
					log.Error("Drop Global Task");
				count++;
			}

		}
	}
}
