using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.DsmCc.Descriptors;
using skyscraper5.DsmCc.Message;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Dvb.DataBroadcasting.Biop;
using skyscraper5.Dvb.DataBroadcasting.Dsm.Event;
using skyscraper5.Dvb.DataBroadcasting.Dsm.Stream;
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Psi.Model;
using skyscraper5.Skyscraper.Plugins;
using Tsubasa.IO;

namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
{
	[SkyscraperPlugin]
	class DataCarouselContestant : Contestant, DataCarouselEventHandler
    {
        public DataCarouselContestant(int pid) : base("DataCarousel", pid)
        {
            ProgramMappingStream pmtStream = new ProgramMappingStream(PmtStreamType.Iso13818_1DsmCc, pid);
            pmtStream.ComponentTag = 3;
            ProgramMapping pmt = new ProgramMapping(1, 2);
            pmt.Streams.Add(pmtStream);
            dataCarouselDecoder = new DataCarouselDecoder(pmtStream, pmt, DataCarouselIntention.NoIntention, this);
            PacketProcessor = new PsiDecoder(pid, dataCarouselDecoder);
        }

        private DataCarouselDecoder dataCarouselDecoder;

        public bool IsModuleWanted(int elementaryPid, ushort moduleId, byte moduleVersion)
        {
            return true;
        }

        public void NotifyOfNewModule(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion)
        {
            Score++;
        }

        public void NotifyModuleDownloadProgress(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion,
            double moduleInfoDownloadProgress)
        {
            Score++;
        }

        private ObjectCarouselContestantHelper _helper;
        public ObjectCarouselEventHandler GetObjectCarouselEventHandler()
        {
            if (_helper == null)
            {
                _helper = new ObjectCarouselContestantHelper(this);
            }
            return _helper;
        }

        public void NotifyDownloadComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion, Stream result, bool isObjectCarousel)
        {
            Score++;
        }

        public void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int pid)
        {
        }

        public void PreventDsmCcModuleRepetition(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
        {
        }

        private class ObjectCarouselContestantHelper : ObjectCarouselEventHandler
        {
            private readonly DataCarouselContestant dataCarouselContestant;

            public ObjectCarouselContestantHelper(DataCarouselContestant dataCarouselContestant)
            {
                this.dataCarouselContestant = dataCarouselContestant;
            }

            public void NotifyFileArrival(VfsFile vfsFile)
            {
                dataCarouselContestant.Score++;
            }

            public void NotifySubStream(ProgramMapping vfsProgramMapping, Tap tap, ushort[] eventIds, Dictionary<uint, string> context, EventList_T eventListT, Info_T infoT)
            {
                dataCarouselContestant.Score++;
            }
        }

        public override void Dispose()
        {
            dataCarouselDecoder.Dispose();
            dataCarouselDecoder = null;
        }

        public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
        {
	        if (programContext.Stream == null)
	        {
		        programContext.Stream = new ProgramMappingStream(PmtStreamType.Iso13818_1PrivateSections, 0x1fff);
		        programContext.Program = new ProgramMapping(0x1fff, 0x1fff);
		        programContext.Program.Streams.Add(programContext.Stream);
	        }
			if (!programContext.Stream.ComponentTag.HasValue)
			{
				skyscraperContext.MakeUpComponentTags(programContext.Program);
			}
			skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid, new DataCarouselDecoder(programContext.Stream, programContext.Program, DataCarouselIntention.NoIntention, skyscraperContext)));
		}

        public override void Introduce(ProgramContext programContext)
        {
	        
        }

        public void ProcessVirtualFilesystem(IFilesystem vfs, ProgramMappingStream pmtPid)
		{
		}
	}
}
