using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper.Scraper.Storage;

namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
{
	internal class MergeDbBlindscanJobs
	{
		public static void RunAsMain()
		{
			ScraperStorageFactoryConnectionManager storageFactoryConnectionManager = ScraperStorageFactoryConnectionManager.GetInstance();
			IScraperStorageFactory storageFactory = storageFactoryConnectionManager.AutoGetDefaultFactory();
			IScraperStroage storage = storageFactory.CreateScraperStroage();

			List<DbBlindscanJob> jobs = GetMergeableBlindscanJobs(storage);
			if (jobs.Count <= 1)
			{
				Console.WriteLine("Nothing to merge!");
				return;
			}

			MergeBlindscanJobs(jobs, storage);
		}

		public static void MergeBlindscanJobs(List<DbBlindscanJob> jobs, IDbBlindscanJobStorage storage)
		{
			//Zuerst schauen ob im Ziel irgendwas gesäubert werden muss.
			DbBlindscanJob mergeTarget = jobs[0];
			DbBlindscanJobPolarizationStatus[] targetCleaningModes = new DbBlindscanJobPolarizationStatus[]
			{
				mergeTarget.HorizontalLowState, mergeTarget.HorizontalHighState, mergeTarget.VerticalLowState, mergeTarget.VerticalHighState
			};
			for (int i = 0; i < targetCleaningModes.Length; i++)
			{
				switch(targetCleaningModes[i])
				{
					case DbBlindscanJobPolarizationStatus.SELECTED_DONE:
						continue;
					case DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING:
						storage.DeleteBlindscanResults(mergeTarget.JobGuid, i);
						continue;
					case DbBlindscanJobPolarizationStatus.SELECTED_WAITING:
						continue;
					default:
						throw new NotImplementedException(targetCleaningModes[i].ToString());
				}
			}

			for (int i = 1; i < jobs.Count; i++)
			{
				DbBlindscanJob mergeSource = jobs[i];
				DbBlindscanJobPolarizationStatus[] modes = new DbBlindscanJobPolarizationStatus[]
				{
					mergeSource.HorizontalLowState, mergeSource.HorizontalHighState, mergeSource.VerticalLowState, mergeSource.VerticalHighState
				};
				for (int j = 0; j < modes.Length; j++)
				{
					bool deleted = false;
					switch(modes[j])
					{
						case DbBlindscanJobPolarizationStatus.NOT_SELECTED:
							continue;
						case DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING:
							storage.DeleteBlindscanJob(mergeSource.JobGuid);
							deleted = true;
							break;
						case DbBlindscanJobPolarizationStatus.SELECTED_WAITING:
							continue;
						case DbBlindscanJobPolarizationStatus.SELECTED_DONE:
							storage.MoveBlScanResultsToAnotherJob(mergeSource.JobGuid, mergeTarget.JobGuid, j);
							continue;
						default:
							throw new NotImplementedException(modes[j].ToString());
					}
					if (!deleted)
						storage.DeleteBlindscanJob(mergeTarget.JobGuid);
				}
			}
		}

		public static List<DbBlindscanJob> GetMergeableBlindscanJobs(IScraperStroage storage)
		{
			
			List<DbBlindscanJob> mergableJobs = new List<DbBlindscanJob>();
			DbBlindscanJob firstJob = null;
			bool hl = false, hh = false, vl = false, vh = false;
			long offset = 0;

			while (true)
			{
				DbBlindscanJob blindscanJob = storage.GetPastBlindscanJob(offset++);
				if (blindscanJob == null)
					break;

				if (blindscanJob.HorizontalLowState == DbBlindscanJobPolarizationStatus.SELECTED_DONE)
					hl = true;
				if (blindscanJob.HorizontalHighState == DbBlindscanJobPolarizationStatus.SELECTED_DONE)
					hh = true;
				if (blindscanJob.VerticalLowState == DbBlindscanJobPolarizationStatus.SELECTED_DONE)
					vl = true;
				if (blindscanJob.VerticalHighState == DbBlindscanJobPolarizationStatus.SELECTED_DONE)
					vh = true;

				if (firstJob == null)
				{
					firstJob = blindscanJob;
					mergableJobs.Add(firstJob);
					continue;
				}

				if (blindscanJob.DiseqCIndex != firstJob.DiseqCIndex)
					break;
				if (!blindscanJob.SatPosition.Equals(firstJob.SatPosition))
					break;
				if (!blindscanJob.TunerMAC.Equals(firstJob.TunerMAC))
					break;
				if (blindscanJob.TunerStandard != firstJob.TunerStandard)
					break;

				mergableJobs.Add(blindscanJob);

				if (hl && hh && vl && vh)
					break;
			}

			mergableJobs.Reverse();
			return mergableJobs;
		}
	}
}
