using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using SupportClasses;

namespace DataClients
{
	public class FileClient
	{
		private char split = _Directory.Slash;
		//private string dir = @"Y:\data";
		//private string dir = @"C:\data";
		private string dir;
		public string Dir {
			get { return dir; }
			set { dir = value; }
		}


		public FileClient()
		{
			//fileClient(@"/archive_rmt/data");
			fileClient(@"Y:\data");
			//fileClient(@"C:\data");
		}
		public FileClient(string directory)
		{
			fileClient(directory);
		}
		private void fileClient(string directory)
		{
			TempDir.StartCkeckDir();
			Dir = directory;
		}

		public byte[] GetFile(DateTime time, ushort vdp, ushort index)
		{
			var name = time.ToString("yyyyMMdd") + "." + vdp.ToString("D2") + index.ToString("D1");
			var tmpFileName = TempDir.GetTempDirectory() + split + name;

			if (!TempDir.IsExist(name))
			{
				if (!CheckArchive(time, vdp)) return new byte[0];
				if (!ExtractArchive(time, vdp)) return new byte[0];
			}
			if (!TempDir.IsExist(name)) return new byte[0];
			while (TempDir.IsProtect(name)) Thread.Sleep(1000);
			TempDir.AddProtect(name);
			using (var fs = (Stream)File.OpenRead(tmpFileName))
			{
				var result = new List<byte>();
				try
				{
					for (var i = 0; i < fs.Length; i++)
						result.Add((byte)fs.ReadByte());
					return result.ToArray();
				}
				catch (Exception e)
				{
					Logger.Add("Can't read file: " + name, Logger.Level.error);
					Logger.Add(e.Message, Logger.Level.error);
					Logger.Add(e.StackTrace, Logger.Level.error);
					return new byte[0];
				}
				finally
				{
					TempDir.RemoveProtect(name);
				}
			}
		}

		private bool CheckArchive(DateTime time, ushort vdp)
		{
			var a =
				dir + split +
				time.Year.ToString("D4") + split +
				time.Month.ToString("D2") + split +
				time.Day.ToString("D2") + split +
				vdp.ToString("D2");
			return (File.Exists(a + ".tar") || File.Exists(a + ".tar.gz"));
		}
		private bool ExtractArchive(DateTime time, ushort vdp)
		{
			var tmp =
				dir + split +
				time.Year.ToString("D4") + split +
				time.Month.ToString("D2") + split +
				time.Day.ToString("D2") + split +
				vdp.ToString("D2");
			if (File.Exists(tmp + ".tar"))
			{
				ExtractTar(tmp + ".tar", TempDir.GetTempDirectory());
				return true;
			}
			else if (File.Exists(tmp + ".tar.gz"))
			{
				ExtractTarGZ(tmp + ".tar.gz", TempDir.GetTempDirectory());
				return true;
			}
			return false;
		}
		private void ExtractTarGZ(String gzArchiveName, String destFolder)
		{
			using (var a = (Stream)File.OpenRead(gzArchiveName))
			using (var b = (Stream)new GZipInputStream(a))
				try
				{
					using (var c = TarArchive.CreateInputTarArchive(b))
						c.ExtractContents(destFolder);
				}
				catch (Exception e)
				{
					Logger.Add("Can't extract: " + gzArchiveName, Logger.Level.error);
					Logger.Add(e.Message, Logger.Level.error);
					Logger.Add(e.StackTrace, Logger.Level.error);
				}
		}
		private void ExtractTar(String tarFileName, String destFolder)
		{
			using (var a = (Stream)File.OpenRead(tarFileName))
				try
				{
					using (var b = TarArchive.CreateInputTarArchive(a))
						b.ExtractContents(destFolder);
				}
				catch (Exception e)
				{
					Logger.Add("Can't extract: " + tarFileName, Logger.Level.error);
					Logger.Add(e.Message, Logger.Level.error);
					Logger.Add(e.StackTrace, Logger.Level.error);
				}
		}
	}
}
