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

namespace skyscraper5.Data.PostgreSql
{
	public partial class PostgresqlDataStore
	{
		private HashSet<DatabaseKeyDsmCcModule> _blacklistedDsmCcModules;
		public bool IsDsmCcModuleBlacklisted(int currentNetworkId, int currentTransportStreamId, int elementaryPid, ushort moduleId, byte moduleVersion)
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "SELECT MAX(progress) FROM dsmcc_modules_blacklist WHERE cnid = @cnid AND ctsid = @ctsid AND elementary_pid = @pid AND module_id = @moduleId AND module_version = @moduleVersion";
				command.Parameters.AddWithValue("@cnid",NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
				command.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
				command.Parameters.AddWithValue("@pid", NpgsqlTypes.NpgsqlDbType.Integer, elementaryPid);
				command.Parameters.AddWithValue("@moduleId", NpgsqlTypes.NpgsqlDbType.Integer, (int)moduleId);
				command.Parameters.AddWithValue("@moduleVersion", NpgsqlTypes.NpgsqlDbType.Integer, (int)moduleVersion);
				NpgsqlDataReader dataReader = command.ExecuteReader();
				if (!dataReader.Read())
				{
					dataReader.Close();
					command.Dispose();
					return false;
				}
				if (dataReader.IsDBNull(0))
				{
					dataReader.Close();
					command.Dispose();
					return false;
				}
				double bestProgress = dataReader.GetDouble(0);
				dataReader.Close();
				command.Dispose();

				command = connection.CreateCommand();
				command.CommandText = "SELECT COUNT(*) FROM dsmcc_modules_blacklist WHERE cnid = @cnid AND ctsid = @ctsid AND elementary_pid = @pid AND module_id = @moduleId AND module_version = @moduleVersion AND progress = @progress";
				command.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
				command.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
				command.Parameters.AddWithValue("@pid", NpgsqlTypes.NpgsqlDbType.Integer, elementaryPid);
				command.Parameters.AddWithValue("@moduleId", NpgsqlTypes.NpgsqlDbType.Integer, (int)moduleId);
				command.Parameters.AddWithValue("@moduleVersion", NpgsqlTypes.NpgsqlDbType.Integer, (int)moduleVersion);
				command.Parameters.AddWithValue("@progress", NpgsqlTypes.NpgsqlDbType.Double, bestProgress);
				dataReader = command.ExecuteReader();
				dataReader.Read();
				long numFailures = dataReader.GetInt64(0);
				dataReader.Close();
				command.Dispose();
				connection.Close();
				return numFailures >= 3;
			}
		}

		public void FailDsmCcDownload(DatabaseKeyDsmCcModule key, double value)
		{
			using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
				connection.Open();
				NpgsqlCommand command = connection.CreateCommand();
				command.CommandText = "INSERT INTO dsmcc_modules_blacklist (cnid, ctsid, elementary_pid, module_id, module_version, progress) VALUES (@cnid,@ctsid,@pid,@moduleId,@moduleVersion,@progress)";
				command.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, key.CurrentNetworkId);
				command.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, key.CurrentTransportStreamId);
				command.Parameters.AddWithValue("@pid", NpgsqlTypes.NpgsqlDbType.Integer, key.ElementaryPid);
				command.Parameters.AddWithValue("@moduleId", NpgsqlTypes.NpgsqlDbType.Integer, (int)key.ModuleId);
				command.Parameters.AddWithValue("@moduleVersion", NpgsqlTypes.NpgsqlDbType.Integer, (int)key.ModuleVersion);
				command.Parameters.AddWithValue("@progress", NpgsqlTypes.NpgsqlDbType.Double, value);
				int result = command.ExecuteNonQuery();
				if (result != 1)
					throw new NpgsqlException(String.Format("Excepted to write 1 line, but wrote {0}", result));
				command.Dispose();
				connection.Close();
			}
		}
	}
}
