using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
using skyscraper8.Mpeg2.Psi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper8.Experimentals.NdsSsu
{
	[SkyscraperPlugin]
	internal class NdsSsuDetector : Contestant, NdsSsuHandler
	{
		public NdsSsuDetector(int pid) : base("NDS France SSU", pid)
		{
			PacketProcessor = new PsiDecoder(pid, new NdsSsuDetectorWorker(this, pid));
		}

		public override void Dispose()
		{
			PacketProcessor = null;
		}

		public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
		{
			skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid,new NdsSsuParser(skyscraperContext,pid)));
		}

		public override void Introduce(ProgramContext programContext)
		{
		}

		class NdsSsuDetectorWorker : PrivateSectionParser
		{
			private readonly NdsSsuHandler _handler;
			private readonly int _pid;
			private bool[] tidExtensions;

			public NdsSsuDetectorWorker(NdsSsuHandler handler, int pid)
			{
				_handler = handler;
				_pid = pid;
			}

			protected override void HandleTable(byte tableId, int sourcePid, byte[] payload)
			{
				_handler.OnNdsSsuError(_pid, NdsSsuError.SectionSyntaxIndicatorMissing);
			}

			protected override void HandleTable(byte tableId, int sourcePid, byte sectionNumber, byte lastSectionNumber, ushort tableIdExtension,
				byte[] payload)
			{
				if (tableId != 0x9e)
				{
					_handler.OnNdsSsuError(_pid,NdsSsuError.WrongTable);
					return;
				}

				if (payload[0] >= 0x02)
				{
					_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
					return;
				}

				if (payload[1] != 0xff)
				{
					_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
					return;
				}

				if (payload[2] != 0x00)
				{
					_handler.OnNdsSsuError(_pid, NdsSsuError.InvalidMagic);
					return;
				}

				if (payload[3] > 0x10)
				{
					_handler.OnNdsSsuError(_pid,NdsSsuError.InvalidMagic);
					return;
				}

				if (tidExtensions == null)
					tidExtensions = new bool[ushort.MaxValue];

				if (tidExtensions[tableIdExtension])
				{
					_handler.OnNdsSsuProgress(_pid,tableIdExtension, sectionNumber, lastSectionNumber, false);
				}
				else
				{
					_handler.OnNdsSsuFileAnnouncement(_pid,tableIdExtension);
					tidExtensions[tableIdExtension] = true;
				}
			}
		}

		public void OnNdsSsuError(NdsSsuError error)
		{
			Score--;
		}

		public void OnNdsSsuError(int pid, NdsSsuError error)
		{
			Score--;
		}

		private int maxNumFiles;
		private int numFiles;
		public void OnNdsSsuFileAnnouncement(int pid, ushort tableIdExtension)
		{
			if (pid == 0x157e)
				ToString();

			if (maxNumFiles == 0)
			{
				maxNumFiles = 2;
				return;
			}

			numFiles++;
			if (numFiles == maxNumFiles)
			{
				maxNumFiles *= 2;
				Score--;
			}
		}

		public void OnNdsSsuFileComplete(int pid, ushort tableIdExtension, NdsSsuDataMap dataMap)
		{
			throw new NotImplementedException();
		}

		public void OnNdsSsuProgress(int pid, ushort tableIdExtension, int blocksDone, int blocksTotal, bool theresMore)
		{
			if (pid == 0x157e)
				ToString();

			Score++;
		}

		public bool TestNdsSsuFileExists(int pid, ushort tableIdExtension)
		{
			throw new NotImplementedException();
		}
	}
}
