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 skyscraper8.DvbNip;
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 };
		}

		
	}

}
