using moe.yo3explorer.skyscraper8.DVBI.Model;
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Skyscraper;
using skyscraper8.DvbNip;
using skyscraper8.Experimentals.NdsSsu;
using skyscraper8.Ietf.FLUTE;
using skyscraper8.SimpleServiceDiscoveryProtocol;
using skyscraper8.Skyscraper.Drawing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace skyscraper8.Skyscraper.Scraper.Storage.Tar
{
	public class TarObjectStorage : ObjectStorage
	{
		public TarObjectStorage(FileInfo fi)
		{
			tarFileInfo = fi;
			tarStream = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
			tarArchive = new TarArchive(tarStream);
		}

		private FileInfo tarFileInfo;
		private Stream tarStream;
		private TarArchive tarArchive;

		public bool SsdpDeviceKnown(SsdpDevice ssdpDevice)
		{
			string filename = string.Format("ssdp/{0}.xml", ssdpDevice.UniqueServiceName.SanitizeFileName());
			return tarArchive.HasEntry(filename);
		}

		public void SsdpStoreMetadata(SsdpDevice ssdpDevice, byte[] ssdpMetadataByteArray)
		{
			string filename = string.Format("ssdp/{0}.xml", ssdpDevice.UniqueServiceName.SanitizeFileName());
			tarArchive.WriteEntry(filename, ssdpMetadataByteArray);
		}

		public byte[] SsdpGetMetadata(SsdpDevice ssdpDevice)
		{
			string filename = string.Format("ssdp/{0}.xml", ssdpDevice.UniqueServiceName.SanitizeFileName());
			return tarArchive.ReadEntry(filename);
		}

		public bool ObjectCarouselFileArrival(VfsFile vfsFile, int transportStreamId, int networkId)
		{
			string filename = string.Format("dsm-cc/objects/{0}/{1}/{2}/{3}", networkId, transportStreamId, vfsFile.SourcePid, vfsFile.ToString());
			if (tarArchive.HasEntry(filename))
			{
				return false;
			}
			else
			{
				tarArchive.WriteEntry(filename, vfsFile.FileContent);
				return true;
			}
		}

		public void DataCarouselModuleArrival(int currentNetworkId, int currentTransportStreamId, int elementaryPid,
			ushort moduleModuleId, byte moduleModuleVersion, Stream result)
		{
			string filename = string.Format("dsm-ccc/{0}/{1}/{2}/{3}_V{4}.bin", currentNetworkId, currentTransportStreamId, elementaryPid, moduleModuleId, moduleModuleVersion);
			tarArchive.WriteEntry(filename, result);
		}

		public bool IsDsmCcModuleWanted(int currentNetworkId, int currentTransportStreamId, int elementaryPid, ushort moduleId,
			byte moduleVersion)
		{
			string filename = string.Format("dsm-ccc/{0}/{1}/{2}/{3}_V{4}.bin", currentNetworkId, currentTransportStreamId, elementaryPid, moduleId, moduleVersion);
			return !tarArchive.HasEntry(filename);
		}

		public bool TestForFramegrab(int currentNetworkId, int transportStreamId, ushort mappingProgramNumber,
			int mappingStreamElementaryPid)
		{
			string filename = string.Format("screenshots/master/{0}/{1}/{2}_{3}.jpg", currentNetworkId, transportStreamId, mappingProgramNumber, mappingStreamElementaryPid);
			return tarArchive.HasEntry(filename);
		}

		public void StoreFramegrab(int currentNetworkId, int transportStreamId, ushort mappingProgramNumber, ushort pid,
			byte[] imageData)
		{
			string filename = string.Format("screenshots/master/{0}/{1}/{2}_{3}.jpg", currentNetworkId, transportStreamId, mappingProgramNumber, pid);
			tarArchive.WriteEntry(filename, imageData);
		}

		public void WaitForCompletion()
		{
		}
		
		public void UiSetVersion(int version)
		{
			throw new NotImplementedException();
		}

		public object[] GetPluginConnector()
		{
			return new object[] { tarArchive };
		}
		
		public void Ping()
		{
			byte[] buffer = new byte[4096];
			for (int i = 0; i < buffer.Length; i++)
			{
				buffer[i] = (byte)i;
			}

			string filename = string.Format("test_write1.dvr");
			if (!tarArchive.HasEntry(filename))
			{
				tarArchive.WriteEntry(filename, buffer);
			}

			byte[] cmpBuffer = tarArchive.ReadEntry(filename);
			if (buffer.Length != cmpBuffer.Length)
			{
				throw new Exception("readback produced invalid length");
			}

			for (int i = 0; i < cmpBuffer.Length; i++)
			{
				if (buffer[i] != cmpBuffer[i])
				{
					throw new Exception("readback produced unexpected result");
				}
			}
		}

		public bool DvbNipTestForFile(string announcedFileContentLocation)
		{
			string filename = "/nip/" + DvbNipUtilities.MakeFilename(announcedFileContentLocation);
			return tarArchive.HasEntry(filename);
		}

		public void DvbNipFileArrival(NipActualCarrierInformation carrier, FluteListener listener)
		{
			string filename = "/nip/" + DvbNipUtilities.MakeFilename(listener.FileAssociation.ContentLocation);
			tarArchive.WriteEntry(filename, listener.ToStream());

		}

		public void StoreIqGraph(Guid jobGuid, long frequency, char polarity, IqChartData plot)
		{
			string filename = String.Format("scandata/{0}/{1}_{2}.iq", jobGuid, frequency, polarity);
			byte[] plotBuffer = plot.SaveToBytes();
			tarArchive.WriteEntry(filename, plotBuffer);
		}

		public void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum)
		{
			string filename = String.Format("scandata/{0}/index.rf", jobGuid);
			byte[] plotBuffer = rfSpectrum.SaveToBytes();
			tarArchive.WriteEntry(filename, plotBuffer);
		}

		public void DeleteIqGraph(Guid jobGuid, int frequency, SatelliteDeliverySystemDescriptor.PolarizationEnum frequencyItem2)
		{
			char polarity = frequencyItem2.ToString()[0];
			string filename = String.Format("scandata/{0}/{1}_{2}.iq.deleted", jobGuid, frequency, polarity);
			tarArchive.WriteEntry(filename, new byte[1]);
		}

		public void DeleteRfSpectrum(Guid selectedGuid)
		{
			string filename = String.Format("scandata/{0}/index.rf.deleted", selectedGuid);
			tarArchive.WriteEntry(filename, new byte[1]);
		}

		public bool OtvSsuTestFile(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, ushort tableIdExtension,
			uint fileId, uint unknown1, uint length)
		{
			string filename = String.Format("otv-ssu/{0}/{1}/{2}/{3}.bin", currentNetworkId, currentTransportStreamId, sourcePid, tableIdExtension);
			return tarArchive.HasEntry(filename);
		}

		public void OnOtvSsuComplete(int? currentNetworkId, int? currentTransportStreamId, int sourcePid, Stream getStream,
			ushort tableIdExtension, uint fileId, uint unknown1, uint length)
		{
			string filename = String.Format("otv-ssu/{0}/{1}/{2}/{3}.bin", currentNetworkId, currentTransportStreamId, sourcePid, tableIdExtension);
			tarArchive.WriteEntry(filename, getStream);
		}

		public void OnNdsSsuComplete(int? currentNetworkId, int? currentTransportStreamId, int pid, ushort tableIdExtension,
			NdsSsuDataMap dataMap)
		{
			string filename = String.Format("nds-ssu/{0}/{1}/{2}/{3}.bin", currentNetworkId, currentTransportStreamId, pid, tableIdExtension);
			tarArchive.WriteEntry(filename, dataMap.WriteToByteArray());
		}

		public bool NdsSsuTestFile(int? currentNetworkId, int? currentTransportStreamId, int pid, ushort tableIdExtension)
		{
			string filename = String.Format("nds-ssu/{0}/{1}/{2}/{3}.bin", currentNetworkId, currentTransportStreamId, pid, tableIdExtension);
			return tarArchive.HasEntry(filename);
		}

		public bool TestForSisDsaci(int nid, int tsid, ushort groupId, int versionNumber)
		{
			string filename = String.Format("dvb-sis/{0}/{1}/Group{2}_Version{3}.xml", nid, tsid, groupId, versionNumber);
			return tarArchive.HasEntry(filename);
		}

		public void StoreSisDsaci(int nid, int tsid, ushort currentDsaGroupId, int versionNumber, Stream dsaci)
		{
			string filename = String.Format("dvb-sis/{0}/{1}/Group{2}_Version{3}.xml", nid, tsid, currentDsaGroupId, versionNumber);
			tarArchive.WriteEntry(filename, dsaci);
		}

		public bool TestForObjectCarouselFileArrival(string vfsFile, int transportStreamId, int pid, int networkId)
		{
			string filename = string.Format("dsm-cc/objects/{0}/{1}/{2}/{3}", networkId, transportStreamId, pid, vfsFile.ToString());
			return tarArchive.HasEntry(filename);
		}

		public byte[] GetObjectCarouselFileArrival(string vfsFile, int transportStreamId, int pid, int networkId)
		{
			string filename = string.Format("dsm-cc/objects/{0}/{1}/{2}/{3}", networkId, transportStreamId, pid, vfsFile.ToString());
			return tarArchive.ReadEntry(filename);
		}

		public byte[] DvbNipGetFile(string path)
		{
			string filename = "/nip/" + DvbNipUtilities.MakeFilename(path);
			return tarArchive.ReadEntry(filename);
		}

		public RfSpectrumData GetRfSpectrum(Guid selectedGuid)
		{
			string filename = String.Format("scandata/{0}/index.rf", selectedGuid);
			byte[] buffer = tarArchive.ReadEntry(filename);
			RfSpectrumData rfSpectrumData = RfSpectrumData.LoadFromStream(new MemoryStream(buffer));
			return rfSpectrumData;
		}

        public bool TestForWneStory(uint sessionId, string filename)
        {
            throw new NotImplementedException();
        }

        public void StoreWneStory(uint sessionId, string filename, Stream value)
        {
            throw new NotImplementedException();
        }
    }
}
