using log4net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper8
{
	internal class HlsProxy
	{
		private readonly DirectoryInfo _sourceDirectory;
		private readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);

		public HlsProxy(DirectoryInfo sourceDirectory)
		{
			_sourceDirectory = sourceDirectory;
		}

		public bool DestructiveMode { get; set; }

		public void Run()
		{
			if (!_sourceDirectory.Exists)
			{
				logger.FatalFormat("{0} does not exist.", _sourceDirectory.FullName);
				return;
			}

			if (_sourceDirectory.GetFiles("*.ts").Length == 0)
			{
				logger.FatalFormat("{0} does not contain any TS files.", _sourceDirectory.FullName);
				return;
			}

			Process process = new Process();
			process.StartInfo = new ProcessStartInfo("vlc");
			process.StartInfo.RedirectStandardInput = true;
			process.StartInfo.RedirectStandardOutput = true;
			process.StartInfo.Arguments = "-";
			process.StartInfo.UseShellExecute = false;
			process.Start();

			HashSet<string> knownFiles = new HashSet<string>();

			while (true)
			{
				if (process.HasExited)
					break;

				FileInfo[] fileInfos = _sourceDirectory.GetFiles("*.ts");
				Array.Sort(fileInfos, (x, y) => x.Name.CompareTo(y.Name));

				bool outputted = false;
				for (int i = 0; i < fileInfos.Length; i++)
				{
					if (!knownFiles.Contains(fileInfos[i].Name))
					{
						logger.InfoFormat("Outputting {0}", fileInfos[i].Name);
						byte[] readAllBytes = File.ReadAllBytes(fileInfos[i].FullName);
						process.StandardInput.BaseStream.Write(readAllBytes, 0, readAllBytes.Length);
						process.StandardInput.BaseStream.Flush();
						knownFiles.Add(fileInfos[i].Name);
						outputted = true;
						if (DestructiveMode)
						{
							try
							{
								File.Delete(fileInfos[i].FullName);
								logger.WarnFormat("Erased {0}", fileInfos[i].Name);
							}
							catch (Exception e)
							{
								logger.WarnFormat("Failed to Erase {0}", fileInfos[i].Name);
							}
						}
						break;
					}
				}

				if (!outputted)
				{
					logger.Info("No new HLS segment yet.");
				}

				Thread.Sleep(1000);
			}
		}
	}
}
