using skyscraper5.Skyscraper.IO;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper;

namespace skyscraper8.Ietf.FLUTE
{
	internal class LctFrame
	{
		public LctFrame(byte[] buffer)
		{
			MemoryStream ms = new MemoryStream(buffer, false);
			byte byteA = ms.ReadUInt8();
			this.Version = (byteA & 0xf0) >> 4;
			this.CongestionControlFlag = (byteA & 0xc0) >> 2;
			this.ProtocolSpecificIndication = (byteA & 0x03);
			byte byteB = ms.ReadUInt8();
			this.TransportSessionIdentifierFlag = (byteB & 0x80) != 0;
			this.TransportObjectIdentifierFlag = (byteB & 0x60) >> 5;
			this.HalfWordFlag = (byteB & 0x10) != 0;
			int reserved = (byteB & 0x0c) >> 2;
			this.CloseSessionFlag = (byteB & 0x02) != 0;
			this.CloseObjectFlag = (byteB & 0x01) != 0;

			if (this.Version != 1)
			{
				Debug.WriteLine(String.Format("FLUTE Version {0}", Version));
				return;
			}

			int HeaderLength = ms.ReadUInt8();
			HeaderLength *= 4;
			HeaderLength -= 4;

			this.Codepoint = ms.ReadUInt8();

			byte[] headerBuffer = ms.ReadBytes(HeaderLength);
			this.LctHeader = new LctHeader(headerBuffer,CongestionControlFlag,TransportSessionIdentifierFlag,TransportObjectIdentifierFlag,HalfWordFlag);
			if (!this.LctHeader.Valid)
				return;

			if (ms.GetAvailableBytes() < 4)
				return;

			this.FecHeader = new FecHeader(ms);

			long avails = ms.GetAvailableBytes();
			if (avails == 0)
				return;

			Payload = ms.ReadBytes(ms.GetAvailableBytes());
			if (Payload[0] == 0x3c && Payload[1] == 0x3f && Payload[2] == 0x78 && Payload[3] == 0x6d &&
			    Payload[4] == 0x6c && Payload[5] == 0x20)
			{
				PayloadAsString = Encoding.UTF8.GetString(Payload);
			}
		}

		public int Version { get; }
		public int CongestionControlFlag { get; }
		public int ProtocolSpecificIndication { get; }
		public byte Codepoint { get; }
		public LctHeader LctHeader { get; }
		public bool TransportSessionIdentifierFlag { get; }
		public int TransportObjectIdentifierFlag { get; }
		public bool HalfWordFlag { get; }
		public bool CloseSessionFlag { get; }
		public bool CloseObjectFlag { get; }
		public FecHeader FecHeader { get; }
		public byte[] Payload { get; }

		public string PayloadAsString { get; private set; }

		public bool PayloadContainsNativeIpMulticastTransportObject
		{
			get
			{
				if (string.IsNullOrEmpty(PayloadAsString))
				{
					return false;
				}
				return PayloadAsString.Contains("NativeIPMulticastTransportObjectTypeCS");
			}
		}
	}
}
