using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Mpeg2;
using skyscraper5.src.Mpeg2.PacketFilter;
using skyscraper8.Skyscraper.Security.Cryptography;

namespace skyscraper8.Mpeg2.PacketFilter
{
	internal class BissDescrambleFilter : IPacketFilter
	{
		public BissDescrambleFilter(byte[] key, params uint[] pids)
		{
			this.key = key;
			if (pids != null)
			{
				if (pids.Length > 0)
				{
					_pidsToDescramble = new List<uint>();
					_pidsToDescramble.AddRange(pids);
				}
			}
		}

		private byte[] key;
		private List<uint> _pidsToDescramble;
		private bool CheckPid(uint pid)
		{
			if (_pidsToDescramble == null)
				return true;
			else 
				return _pidsToDescramble.Contains(pid);
		}

		private DvbCsa2 csa2;

		public bool PassPacket(TsPacket packet)
		{
			if (packet.TSC == 0)
				return true;

			if (!CheckPid(packet.PID))
				return true;

			//Okay, we actually need to do something...
			if (csa2 == null)
			{
				csa2 = new DvbCsa2(key.Length == 8 ? DvbCsa2.EntropyMode.FULL_CW : DvbCsa2.EntropyMode.REDUCE_ENTROPY);
				csa2.SetKeyImpl(key);
			}

			int retsize = 0;
			Span<byte> scrambledPayload = packet.GetPayload();
			byte[] unscrambled = new byte[scrambledPayload.Length];
			csa2.DecryptImpl(scrambledPayload, scrambledPayload.Length, unscrambled, unscrambled.Length, ref retsize);

			packet.SetUnscrambled(unscrambled);
			return true;
		}
	}
}
