using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.DNS.Protocol.ResourceRecords.Records;

namespace skyscraper5.DNS.Protocol.ResourceRecords
{
	internal class ResourceRecordFactory
	{
		public static IList<IResourceRecord> GetAllFromArray(byte[] message, int offset, int count, out int endOffset)
		{
			IList<IResourceRecord> result = new List<IResourceRecord>(count);

			for (int i = 0; i < count; i++)
			{
				try
				{
					result.Add(FromArray(message, offset, out offset));
				}
				catch (ArgumentException ae)
				{
					endOffset = offset;
					return result;
				}
				catch (IndexOutOfRangeException ioore)
				{
					endOffset = offset;
					return result;
				}
			}

			endOffset = offset;
			return result;
		}

		public static IResourceRecord FromArray(byte[] message, int offset, out int endOffest)
		{
			ResourceRecord record = ResourceRecord.FromArray(message, offset, out endOffest);
			int dataOffset = endOffest - record.DataLength;

			if (record.Type == 0)
				return null;

			if (record.DataLength == 0)
				return null;

			switch (record.Type)
			{
				case RecordType.A:
				case RecordType.AAAA:
					return new IPAddressResourceRecord(record);
				case RecordType.NS:
					return new NameServerResourceRecord(record, message, dataOffset);
				case RecordType.CNAME:
					return new CanonicalNameResourceRecord(record, message, dataOffset);
				case RecordType.SOA:
					return new StartOfAuthorityResourceRecord(record, message, dataOffset);
				case RecordType.PTR:
					return new PointerResourceRecord(record, message, dataOffset);
				case RecordType.MX:
					return new MailExchangeResourceRecord(record, message, dataOffset);
				case RecordType.TXT:
					return new TextResourceRecord(record);
				case RecordType.SRV:
					return new ServiceResourceRecord(record, message, dataOffset);
				case RecordType.SVCB:
					return new GeneralPurposeServiceEndpointsRecord(record, message, dataOffset);
				case RecordType.HTTPS:
					return new HttpsSpecificServiceEndspointsRecord(record, message, dataOffset);
				case RecordType.RRSIG:
					return new ResourceRecordSignatureRecord(record, message, dataOffset);
				case RecordType.OPT:
					return new OptionRecord(record, message, dataOffset);
				case RecordType.NSEC3:
					return new NSec3Record(record, message, dataOffset);
				case RecordType.NAPTR:
					return new NamingAuthorityPointerResourceRecord(record, message, dataOffset);
				case RecordType.NSEC:
					return new NSecResourceRecord(record, message, dataOffset);
				case RecordType.DNAME:
					return new DNameResourceRecord(record, message, dataOffset);
				case RecordType.DS:
					return new DelegationSignerResourceRecord(record, message, dataOffset);
				case RecordType.DNSKEY:
					return new DnsKeyResourceRecord(record, message, dataOffset);
				case(RecordType)32768:
					throw new NotImplementedException();
				case (RecordType)32769:
					throw new NotImplementedException();
				default:
					int type = (int)record.Type;
					if (type > 259)
						return null;
					else
						throw new NotImplementedException(record.Type.ToString());
			}
		}

		

	}
}
