using DVBServices;
using skyscraper5.Skyscraper.Scraper;
using skyscraper8.Skyscraper.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper8.EPGCollectorPort.SkyscraperSide.MediaHighway2
{
	internal class Mhw2Scraper : Mhw2EventHandler
	{
		private readonly SkyscraperContext _skyscraperContext;
		private readonly IMhw2Storage storage;

		public Mhw2Scraper(SkyscraperContext skyscraperContext)
		{
			_skyscraperContext = skyscraperContext;
			storage = new Mhw2StorageImpl(skyscraperContext.DataStorage.GetPluginConnector());
			_logger = PluginLogManager.GetLogger(GetType());
		}

		public void OnNonMhw2Traffic(int sourcePid, int sectionTableId, byte mhwType)
		{
		}

		private bool hasChannels;
		public void OnMhw2Channels(int sourcePid, MediaHighway2ChannelSection channelSection)
		{
			if (hasChannels)
				return;
			if (channelSection == null)
				return;
			if (!_skyscraperContext.CurrentNetworkId.HasValue)
				return;
			if (!_skyscraperContext.CurrentTransportStreamId.HasValue)
				return;

			storage.InsertChannels(_skyscraperContext.CurrentNetworkId.Value, _skyscraperContext.CurrentTransportStreamId.Value, channelSection);
			_logger.Log(PluginLogLevel.Info, "Found {0} channels", channelSection.Channels.Count);
			hasChannels = true;
		}

		private bool hasCategories;
		public void OnMhw2Categories(int sourcePid, MediaHighway2CategorySection categorySection)
		{
			if (hasCategories)
				return;
			if (!_skyscraperContext.CurrentNetworkId.HasValue)
				return;
			if (!_skyscraperContext.CurrentTransportStreamId.HasValue)
				return;

			storage.InsertCategories(_skyscraperContext.CurrentNetworkId.Value, _skyscraperContext.CurrentTransportStreamId.Value, categorySection);
			_logger.Log(PluginLogLevel.Info, "Found {0} categories", categorySection.Categories.Count);
			hasCategories = true;
		}

		public void OnMhw2Titles(int sourcePid, MediaHighway2TitleSection titleSection)
		{
			if (_binders == null)
				_binders = new Dictionary<int, Mhw2EventBinder>();

			foreach (MediaHighway2TitleData titleData in titleSection.Titles)
			{
				Mhw2EventBinder currentBinder;
				if (_binders.ContainsKey(titleData.EventID))
				{
					currentBinder = _binders[titleData.EventID];
				}
				else
				{
					currentBinder = new Mhw2EventBinder(titleData.EventID);
					_binders.Add(titleData.EventID, currentBinder);
				}

				if (!currentBinder.TitleDataSeen)
				{
					currentBinder.EventName = titleData.EventName;
					currentBinder.CategoryID = titleData.CategoryID;
					currentBinder.ChannelID = titleData.ChannelID;
					currentBinder.Duration = titleData.Duration;
					currentBinder.MainCategory = titleData.MainCategory;
					currentBinder.StartTime = titleData.StartTime;
					currentBinder.SubCategory = titleData.SubCategory;
					currentBinder.TitleDataSeen = true;
				}

				if (IsBinderComplete(currentBinder))
				{
					StoreBinder(currentBinder);
					_binders.Remove(titleData.EventID);
				}
			}
		}

		public void OnMhw2Summary(int sourcePid, MediaHighway2SummarySection summarySection)
		{
			if (summarySection == null)
				return;

			if (_binders == null)
				_binders = new Dictionary<int, Mhw2EventBinder>();

			Mhw2EventBinder currentBinder;
			if (_binders.ContainsKey(summarySection.SummaryData.EventID))
			{
				currentBinder = _binders[summarySection.SummaryData.EventID];
			}
			else
			{
				currentBinder = new Mhw2EventBinder(summarySection.SummaryData.EventID);
				_binders.Add(summarySection.SummaryData.EventID, currentBinder);
			}
			
			currentBinder.ShortDescription = summarySection.SummaryData.ShortDescription;
			currentBinder.ShortDescriptionSeen = true;
			if (IsBinderComplete(currentBinder))
			{
				StoreBinder(currentBinder);
				_binders.Remove(summarySection.SummaryData.EventID);
			}
		}

		private Dictionary<int,Mhw2EventBinder> _binders;
		private readonly PluginLogger _logger;


		private bool IsBinderComplete(Mhw2EventBinder binder)
		{
			if (!_skyscraperContext.CurrentNetworkId.HasValue)
				return false;
			if (!_skyscraperContext.CurrentTransportStreamId.HasValue)
				return false;
			if (!hasCategories)
				return false;
			if (!hasChannels)
				return false;
			if (!binder.ShortDescriptionSeen)
				return false;
			if (!binder.TitleDataSeen)
				return false;
			return true;
		}

		private void StoreBinder(Mhw2EventBinder binder)
		{
			if (!storage.TestForEvent(_skyscraperContext.CurrentNetworkId.Value, _skyscraperContext.CurrentTransportStreamId.Value, binder))
			{
				_logger.Log(PluginLogLevel.Info, "Event: {0}", binder.EventName);
				storage.InsertEvent(_skyscraperContext.CurrentNetworkId.Value, _skyscraperContext.CurrentTransportStreamId.Value, binder);
			}
		}
	}
}
