using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Ietf.Rfc971;

namespace skyscraper5.Skyscraper
{
    internal class IpPacketFinder
    {
        public static byte[] LookForIpPacket(byte[] gsPacket, int searchDepth = 16)
        {
            int offset;
            return LookForIpPacket(gsPacket, out offset, searchDepth);
        }
        public static byte[] LookForIpPacket(byte[] gsPacket, out int offset, int searchDepth = 16)
        {
            byte[] ipBuffer = new byte[20];

            for (int i = 0; i < searchDepth; i++)
            {
                int v4HeaderEnd = i + 20;
                if (v4HeaderEnd > gsPacket.Length)
                {
                    offset = -1;
                    return null;
                }

                if (gsPacket[i] == 0x45)
                {
                    Array.Copy(gsPacket, i, ipBuffer, 0, ipBuffer.Length);
                    InternetHeader ipv4 = new InternetHeader(ipBuffer);
                    if (!ipv4.ChecksumValid)
                        continue;
                    int payloadStart = i + ipBuffer.Length;
                    int payloadEnd = i + ipv4.TotalLength;
                    if (payloadEnd > gsPacket.Length)
                    {
                        offset = -1;
                        return null;
                    }
                    int packetLength = payloadEnd - i;

                    byte[] finalPacket = new byte[packetLength];
                    Array.Copy(gsPacket, i, finalPacket, 0, packetLength);
                    offset = i;
                    return finalPacket;
                }
            }
            offset = -1;
            return null;
        }

        public static List<byte[]> LookForIpPackets(ReadOnlySpan<byte> gsPacket)
        {
	        List<byte[]> result = null;

	        byte[] ipBuffer = new byte[20];
	        for (int offset = 0; offset < gsPacket.Length; offset++)
	        {
		        int v4HeaderEnd = offset + 20;
		        if (v4HeaderEnd > gsPacket.Length)
			        break;

		        if (gsPacket[offset] == 0x45)
		        {
			        ipBuffer = gsPacket.Slice(offset, 20).ToArray();
			        InternetHeader ipv4 = new(ipBuffer);
			        if (!ipv4.ChecksumValid)
				        continue;
			        int payloadStart = offset + ipBuffer.Length;
			        int payloadEnd = offset + ipv4.TotalLength;
			        if (payloadEnd > gsPacket.Length)
				        break;
			        int packetLength = payloadEnd - offset;

			        byte[] finalPacket = new byte[packetLength];
			        finalPacket = gsPacket.Slice(offset, packetLength).ToArray();
			        if (result == null)
				        result = new List<byte[]>();
			        result.Add(finalPacket);
			        offset = payloadEnd;
		        }
	        }

	        return result;
        }

        public static bool TestForHttpContents(byte[] buffer)
        {
	        for (int i = 0; i < buffer.Length - 5; i++)
		        if (buffer[i] == 0x48)
			        if (buffer[i + 1] == 0x54)
				        if (buffer[i + 2] == 0x54)
					        if (buffer[i + 3] == 0x50)
						        if (buffer[i + 4] == 0x2f)
							        return true;
	        return false;
        }
    }
}
