using System;
using System.Collections.Generic;
using System.Data;
using Npgsql;
using NpgsqlTypes;
using skyscraper5.Dvb.Psi.Model;
using skyscraper5.Dvb.TvAnytime;
using skyscraper5.Skyscraper.Headless;
using skyscraper5.src.InteractionChannel.Model;
using skyscraper5.src.InteractionChannel.Model2;
using skyscraper8.DvbNip;
using skyscraper8.InteractionChannel.Model2;
using skyscraper8.Skyscraper.Scraper.Storage;

namespace skyscraper5.Data.PostgreSql
{
	public partial class PostgresqlDataStore : DataStorage
	{
		public PostgresqlDataStore(NpgsqlConnectionStringBuilder stringBuilder)
		{
			connectionStringBuilder = stringBuilder;
		}

		internal NpgsqlConnectionStringBuilder connectionStringBuilder;

		
		public bool TestForRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo)
		{
			throw new NotImplementedException();
		}

		public void SetRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo)
		{
			throw new NotImplementedException();
		}

		private static void SetNulls(NpgsqlCommand command)
		{
			foreach (NpgsqlParameter param in command.Parameters)
			{
				if (param.Value == null)
				{
					param.Value = DBNull.Value;
				}
			}
		}

		private int? detectedLocation;
		public int? GetCurrentLocationId()
		{
			if (detectedLocation.HasValue)
				return detectedLocation;

			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				Guid? locationUuid = null;
				double? lon = null;
				double? lat = null;

				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "SELECT uuid, ROUND(CAST(gps_lon as numeric),5), ROUND(CAST(gps_lat as numeric),5) FROM skyscraper5_blindscan_jobs\r\nWHERE tuner_std != 1\r\nORDER BY dateupdated DESC";
				NpgsqlDataReader dataReader = command.ExecuteReader();
				if (dataReader.Read())
				{
					locationUuid = dataReader.GetGuid(0);
					lon = dataReader.GetDouble(1);
					lat = dataReader.GetDouble(2);
				}
				dataReader.Close();
				command.Dispose();

				if (!locationUuid.HasValue)
				{
					command = connection.CreateCommand();
					command.CommandText = "SELECT lonround, latround FROM docsis_locations WHERE guess_default = TRUE";
					dataReader = command.ExecuteReader();
					if (dataReader.Read())
					{
						locationUuid = Guid.NewGuid();
						lon = dataReader.GetDouble(0);
						lat = dataReader.GetDouble(1);
					}
					dataReader.Close();
					command.Dispose();
				}

				if (locationUuid.HasValue)
				{
					command = connection.CreateCommand();
					command.CommandText = "SELECT id FROM docsis_locations WHERE lonround = @lon AND latround = @lat";
					command.Parameters.AddWithValue("@lon", NpgsqlDbType.Double, lon.Value);
					command.Parameters.AddWithValue("@lat", NpgsqlDbType.Double, lat.Value);
					dataReader = command.ExecuteReader();
					if (dataReader.Read())
					{
						detectedLocation = dataReader.GetInt32(0);
						dataReader.Close();
						command.Dispose();
						connection.Close();
						return detectedLocation.Value;
					}
					dataReader.Close();

					command = connection.CreateCommand();
					command.CommandText = "INSERT INTO docsis_locations (lonround,latround) VALUES (@lon,@lat) RETURNING id";
					command.Parameters.AddWithValue("@lon", NpgsqlDbType.Double, lon.Value);
					command.Parameters.AddWithValue("@lat", NpgsqlDbType.Double, lat.Value);
					dataReader = command.ExecuteReader();
					dataReader.Read();
					detectedLocation = dataReader.GetInt32(0);
					dataReader.Close();
					connection.Close();
					return detectedLocation.Value;
				}
				connection.Close();
			}

			throw new NotImplementedException();
		}

		public HeadlessJob GetQueuedJob()
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "SELECT uuid, jobtype, iarg1, sarg1 FROM skyscraper5_job_queue WHERE completed = FALSE ORDER BY dateadded";
				NpgsqlDataReader dataReader = command.ExecuteReader();
				HeadlessJob job = null;
				if (dataReader.Read())
				{
					job = new HeadlessJob();
					job.uuid = dataReader.GetGuid(0);
					job.jobType = (HeadlessJobType)dataReader.GetInt32(1);
					if (!dataReader.IsDBNull(2))
						job.iArg1 = dataReader.GetInt32(2);
					if (!dataReader.IsDBNull(3))
						job.sArg1 = dataReader.GetString(3);
				}
				dataReader.Close();
				command.Dispose();
				connection.Close();
				return job;
			}
		}

		public void SetQueuedJobComplete(HeadlessJob headlessJob)
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "UPDATE skyscraper5_job_queue SET completed = TRUE, dateupdated = CURRENT_TIMESTAMP, version = version + 1 WHERE uuid = @uuid";
				command.Parameters.AddWithValue("@uuid", NpgsqlDbType.Uuid, headlessJob.uuid);
				int executeNonQuery = command.ExecuteNonQuery();
				if (executeNonQuery != 1)
					throw new DataException(String.Format("Didn't expect to update {0} rows.", executeNonQuery));
				command.Dispose();
				connection.Close();
			}
		}

		private PostgresqlToken pluginToken;
		public object[] GetPluginConnector()
		{
			if (pluginToken == null)
			{
				pluginToken = new PostgresqlToken(this);
			}
			return new object[] { pluginToken };
		}

		public void InsertUiBlindscanSettingHistory(int settingsWindowBlScanTunerSelection,
			int multitunerMode, int settingsWindowSetFilterTunerSelection,
			int settingsWindowDiseqc, bool settingsWindowCollectIqGraphs, bool settingsWindowCollectRfSpectrum,
			bool settingsWindowCaptureFile, int settingsWindowSatellite, int settingsWindowLnb, int dish,
			bool settingsWindowScanHorizontalLow, bool settingsWindowScanHorizontalHigh, bool settingsWindowScanVerticalLow,
			bool settingsWindowScanVerticalHigh)
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText =
					"INSERT INTO ui_blindscan_setting_history VALUES (DEFAULT,@bstselection,@ustfsfilter,@sftselection,@diseqc,@cigraphs,@crspectrum,@cfilters,@satellite,@lnb,@dish,@hl,@hh,@vl,@vh);";
				command.Parameters.AddWithValue("@bstselection", NpgsqlDbType.Integer, settingsWindowBlScanTunerSelection);
				command.Parameters.AddWithValue("@ustfsfilter", NpgsqlDbType.Integer, multitunerMode);
				command.Parameters.AddWithValue("@sftselection", NpgsqlDbType.Integer, settingsWindowSetFilterTunerSelection);
				command.Parameters.AddWithValue("@diseqc", NpgsqlDbType.Integer, settingsWindowDiseqc);
				command.Parameters.AddWithValue("@cigraphs", NpgsqlDbType.Boolean, settingsWindowCollectIqGraphs);
				command.Parameters.AddWithValue("@crspectrum", NpgsqlDbType.Boolean, settingsWindowCollectRfSpectrum);
				command.Parameters.AddWithValue("@cfilters", NpgsqlDbType.Boolean, settingsWindowCaptureFile);
				command.Parameters.AddWithValue("@satellite", NpgsqlDbType.Integer, settingsWindowSatellite);
				command.Parameters.AddWithValue("@lnb", NpgsqlDbType.Integer, settingsWindowLnb);
				command.Parameters.AddWithValue("@dish", NpgsqlDbType.Integer, dish);
				command.Parameters.AddWithValue("@hl", NpgsqlDbType.Boolean, settingsWindowScanHorizontalLow);
				command.Parameters.AddWithValue("@hh", NpgsqlDbType.Boolean, settingsWindowScanHorizontalHigh);
				command.Parameters.AddWithValue("@vl", NpgsqlDbType.Boolean, settingsWindowScanVerticalLow);
				command.Parameters.AddWithValue("@vh", NpgsqlDbType.Boolean, settingsWindowScanVerticalHigh);
				command.ExecuteNonQuery();
				connection.Close();
			}
		}

		public object[] GetLastUiBlindscanSettings()
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "SELECT * FROM ui_blindscan_setting_history WHERE dateadded = (SELECT MAX(dateadded) FROM ui_blindscan_setting_history)";
				NpgsqlDataReader dataReader = command.ExecuteReader();
				object[] result = null;
				if (dataReader.Read())
				{
					int fields = dataReader.FieldCount;
					result = new object[fields];
					for (int i = 0; i < fields; i++)
					{
						result[i] = dataReader.GetValue(i);
					}
				}
				dataReader.Close();
				command.Dispose();
				connection.Close();
				return result;
			}
		}

		public bool TestForTerminalBurstTimePlan2(ushort interactiveNetworkId, byte tbtp2GroupId, byte frameFrameNumber)
		{
			throw new NotImplementedException();
		}

		public void StoreTerminalBurstTimePlan2(ushort interactiveNetworkId, byte tbtp2GroupId, Tbtp2.Frame frame)
		{
			throw new NotImplementedException();
		}

		public bool TestForFrameComposition2(ushort networkId, Fct2.Frame fct2)
		{
			throw new NotImplementedException();
		}

		public void InsertFct2Frame(ushort networkId, Fct2.Frame frame)
		{
			throw new NotImplementedException();
		}

		public bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType)
		{
			throw new NotImplementedException();
		}

		public void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType)
		{
			throw new NotImplementedException();
		}

		public bool TestForRmt(Rmt rmt)
		{
			return true;
		}

		public void InsertRmt(Rmt rmt)
		{
			throw new NotImplementedException();
		}
	}

}
