using System;
using System.Collections.Generic;
using System.IO;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;

namespace skyscraper5.Scorcher
{
	internal class TotGenerator : PsiGenerator
	{
		public TotGenerator() : base(new TimeSpan(0,0,1), 0x0014)
		{
			descriptors = new List<TsDescriptor>();
		}

		private List<TsDescriptor> descriptors;

		private byte[] SerializeDescriptors()
		{
			MemoryStream ms = new MemoryStream();
			foreach (TsDescriptor descriptor in descriptors)
			{
				ms.WriteUInt8(descriptor.GetDescriptorId());    //descriptor_tag

				byte[] descriptorBytes = descriptor.Serialize();
				ms.WriteUInt8((byte)descriptorBytes.Length);    //descriptor_length
				ms.Write(descriptorBytes, 0, descriptorBytes.Length);
			}
			return ms.ToArray();
		}

		public override byte[] BuildPsi()
		{
			byte[] descriptors = SerializeDescriptors();
			int descriptorsLoopLength = descriptors.Length;
			int sectionLength = 5 + 2 + descriptorsLoopLength + 4;

			//----------------------------------
			MemoryStream ms = new MemoryStream();
			ms.WriteUInt8(0x73);

			byte byte1 = 0;
			//section syntax indicator
			byte1 |= 0x40;	//reserved_future_use
			byte1 |= 0x30;  //reserved
			byte1 += (byte)((sectionLength & 0x0f00) >> 8);
			ms.WriteUInt8(byte1);   //section length, part 1

			byte byte2 = (byte)(sectionLength & 0x00ff);
			ms.WriteUInt8(byte2);   //section length, part 2

			ms.Write(TdtGenerator.EncodeMjd(DateTime.Now), 0, 5);

			byte byte3 = 0;
			byte3 |= 0xf0;  //reserved
			byte3 += (byte)((descriptorsLoopLength & 0x0f00) >> 8);
			ms.WriteUInt8(byte3);   //section length, part 1

			byte byte4 = (byte)(descriptorsLoopLength & 0x00ff);
			ms.WriteUInt8(byte4);   //section length, part 2

			ms.Write(descriptors, 0, descriptors.Length);

			uint crc = DvbCrc32.CreateCrc(ms, 0, (int)ms.Position);
			ms.WriteUInt32BE(crc);

			return ms.ToArray();
		}
	}
}
