using System;
using System.Collections.ObjectModel;
using System.Threading;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.Skyscraper.Gps
{
	public class GpsManager
	{
		/// <summary>
		/// Reads the ID of the GPS Receiver configured in skyscraper5.ini
		/// </summary>
		/// <returns>The ID of the GPS Receiver configured in skyscraper5.ini, or 0 if none is configured.</returns>
		public static int GetConfiguredGpsId()
		{
			Ini ini = PluginManager.GetInstance().Ini;
			if (ini == null)
				return 0;

			if (!ini.ContainsKey("startup"))
				return 0;

			IniSection section = ini["startup"];
			if (!section.ContainsKey("gps"))
				return 0;

			return Convert.ToInt32(section["gps"]);
		}

		/// <summary>
		/// Retrieves the factory for a GPS receiver.
		/// </summary>
		/// <param name="id">The ID of the GPS Receiver you want.</param>
		/// <returns>An instance of a fitting Factory class, or null if the GPS receiver is not known.</returns>
		public static IGpsReceiverFactory GetGpsReceiverFactoryById(int id)
		{
			ReadOnlyDictionary<int, IGpsReceiverFactory> gpsReceiverFactories = PluginManager.GetInstance().GetGpsReceiverFactories();
			if (gpsReceiverFactories.ContainsKey(id))
				return gpsReceiverFactories[id];
			else
				return null;
		}

		/// <summary>
		/// Populates a GPS receiever factory from the settings found in skyscraper5.ini
		/// </summary>
		/// <param name="factory">The factory to configure.</param>
		public static void AutoconfigureGpsReceiverFactory(IGpsReceiverFactory factory)
		{
			long id = PluginPrioritySorter.GetPriorityFromObject(factory);
			string catName = String.Format("gps{0}", id);
			PluginManager.GetInstance().AutoconfigureObject(catName, factory);
		}

		internal static void GpsTest()
		{
			int configuredGpsId = GetConfiguredGpsId();
			IGpsReceiverFactory factory = GetGpsReceiverFactoryById(configuredGpsId);
			AutoconfigureGpsReceiverFactory(factory);
			IGpsReceiver gpsReceiver = factory.CreateGpsReceiver();
			
			Console.WriteLine("Starting GPS Receiver...");
			gpsReceiver.Start();

			Console.Write("Waiting for GPS Data to become available");
			int waiter = 1;
			while (!gpsReceiver.HasLock)
			{
				Thread.Sleep(waiter);
				waiter *= 2;
				if (waiter > 1000)
					waiter = 1000;
				Console.Write(".");
			}
			Console.WriteLine("...OK!");

			Console.WriteLine();
			Console.WriteLine("Lock at: {0}", gpsReceiver.Coordinate);
			Console.WriteLine();

			gpsReceiver.Stop();
		}

		public static ReadOnlyDictionary<int, IGpsReceiverFactory> GetGpsTunerFactories()
		{
			ReadOnlyDictionary<int, IGpsReceiverFactory> gpsReceiverFactories = PluginManager.GetInstance().GetGpsReceiverFactories();
			return gpsReceiverFactories;
		}
	}
}
