using AprsSharp.Parsers.Aprs;
using GeoCoordinatePortable;
using skyscraper5.Aprs.AprsSharp;
using skyscraper5.Skyscraper.Scraper.Storage.InMemory.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;

namespace skyscraper5.Aprs.AprsStorage
{
	internal class AprsInMemoryStorage : LX9SESStorage
	{
		public AprsInMemoryStorage(InMemoryPluginToken inMemoryPluginToken)
		{
			this.aprsData = new HashSet<InMemoryAprsData>();
			inMemoryPluginToken.Data["aprsData"] = this.aprsData;
		}

		private HashSet<InMemoryAprsData> aprsData;

		public bool AprsPosition(DateTime currentTime, string packetSender, GeoCoordinate positionCoordinates, string? piComment)
		{
			InMemoryAprsData aprsEntry = aprsData.FirstOrDefault(x => x.CallSign.Equals(packetSender));
			if (aprsEntry == null)
			{
				aprsEntry = new InMemoryAprsData(packetSender);
				aprsData.Add(aprsEntry);
			}

			bool result = aprsEntry.LastSeen < currentTime;
			if (!result)
				return false;
			aprsEntry.LastSeen = currentTime;
			result = aprsEntry.Longitude != positionCoordinates.Longitude || aprsEntry.Latitude != positionCoordinates.Latitude;
			if (result)
			{
				aprsEntry.Longitude = positionCoordinates.Longitude;
				aprsEntry.Latitude = positionCoordinates.Latitude;
				aprsEntry.Comment = piComment;
				aprsEntry.TimesMoved++;
				if (aprsEntry.TimesMoved > 2)
					Console.WriteLine("{0} is actually moving", packetSender);
				return true;
			}
			return false;
		}

		public bool AprsWeatherReport(DateTime currentTime, string packetSender, WeatherInfo wi)
		{
			InMemoryAprsData aprsEntry = aprsData.FirstOrDefault(x => x.CallSign.Equals(packetSender));
			if (aprsEntry == null)
			{
				return false;
			}

			return aprsEntry.WeatherTimestamps.Add(currentTime);
		}


		public void AprsMessage(string sender, DateTime currentTime, string receiver, string message)
		{

		}

		public bool AprsStationCapabilities(string packetSender, StationCapabilities stationCapabilities)
		{
			InMemoryAprsData aprsEntry = aprsData.FirstOrDefault(x => x.CallSign.Equals(packetSender));
			if (aprsEntry == null)
				return false;

			if (aprsEntry.LocalStations != stationCapabilities.LocalStations || aprsEntry.MessageCount != stationCapabilities.MessageCount)
			{
				aprsEntry.LocalStations = stationCapabilities.LocalStations;
				aprsEntry.MessageCount = stationCapabilities.MessageCount;
				return true;
			}

			return false;
		}

		public bool AprsGpsSentence(DateTime currentTime, string packetSender, double? course, double? magneticVariation, double? speed)
		{
			InMemoryAprsData aprsEntry = aprsData.FirstOrDefault(x => x.CallSign.Equals(packetSender));
			if (aprsEntry == null)
			{
				aprsEntry = new InMemoryAprsData(packetSender);
				aprsData.Add(aprsEntry);
			}

			bool result = false;
			if (course.HasValue && !double.IsNaN(course.Value))
			{
				if (!aprsEntry.Course.Equals(course))
				{
					aprsEntry.Course = course;
					result = true;
				}
			}

			if (magneticVariation.HasValue && !double.IsNaN(magneticVariation.Value))
			{
				if (!aprsEntry.MagneticVariation.Equals(magneticVariation))
				{
					aprsEntry.MagneticVariation = magneticVariation;
					result = true;
				}
			}

			if (speed.HasValue && !double.IsNaN(speed.Value))
			{
				if (!aprsEntry.Speed.Equals(speed))
				{
					aprsEntry.Speed = speed;
					result = true;
				}
			}

			return result;
		}
	}
}
