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

namespace skyscraper5.Data.PostgreSql
{
    public partial class PostgresqlDataStore
    {
        private HashSet<DatabaseKeyPatEntry> knownPats;
        public bool StorePatEntry(int currentNetworkId, int currentTransportStreamId, int pmtPid, ushort programId)
        {
            if (knownPats == null)
                knownPats = new HashSet<DatabaseKeyPatEntry>();

            DatabaseKeyPatEntry key = new DatabaseKeyPatEntry(currentNetworkId, currentTransportStreamId, programId);
            if (knownPats.Contains(key))
            {
                return true;
            }

            bool alreadyKnownInDb = false;
            using (NpgsqlConnection conn = new NpgsqlConnection(connectionStringBuilder.ToString()))
			{
                conn.Open();
				alreadyKnownInDb = TestPat(currentNetworkId, currentTransportStreamId, programId, key, alreadyKnownInDb, conn);
                conn.Close();
			}

			if (alreadyKnownInDb)
                return true;

            EnqueueTask(x => WritePat(x, currentNetworkId, currentTransportStreamId, pmtPid, programId));
            knownPats.Add(key);
            return false;
        }

		private bool TestPat(int currentNetworkId, int currentTransportStreamId, ushort programId, DatabaseKeyPatEntry key, bool alreadyKnownInDb, NpgsqlConnection conn)
		{
			NpgsqlCommand command = conn.CreateCommand();
			command.CommandText = "SELECT dateadded FROM dvb_pat WHERE cnid = @cnid AND ctsid = @ctsid AND program_id = @program_id";
			command.Parameters.AddWithValue("@cnid", NpgsqlDbType.Integer, currentNetworkId);
			command.Parameters.AddWithValue("@ctsid", NpgsqlDbType.Integer, currentTransportStreamId);
			command.Parameters.AddWithValue("@program_id", NpgsqlDbType.Integer, (int)programId);
			NpgsqlDataReader dataReader = command.ExecuteReader();
			if (dataReader.Read())
			{
				alreadyKnownInDb = true;
				knownPats.Add(key);
			}
			dataReader.Close();
			return alreadyKnownInDb;
		}

		private void WritePat(NpgsqlConnection conn, int currentNetworkId, int currentTransportStreamId, int pmtPid, ushort programId)
        {
			DatabaseKeyPatEntry key = new DatabaseKeyPatEntry(currentNetworkId, currentTransportStreamId, programId);
            if (!TestPat(currentNetworkId, currentTransportStreamId, programId, key, false, conn))
            {
                NpgsqlCommand command = conn.CreateCommand();
                command.CommandText = "INSERT INTO dvb_pat " +
                                      "(cnid, ctsid, pmt_pid, program_id) " +
                                      "VALUES " +
                                      "(@cnid, @ctsid, @pmt_pid, @program_id)";
                command.Parameters.AddWithValue("@cnid", NpgsqlDbType.Integer, currentNetworkId);
                command.Parameters.AddWithValue("@ctsid", NpgsqlDbType.Integer, currentTransportStreamId);
                command.Parameters.AddWithValue("@pmt_pid", NpgsqlDbType.Integer, pmtPid);
                command.Parameters.AddWithValue("@program_id", NpgsqlDbType.Integer, (int)programId);
                command.ExecuteNonQuery();
            }
        }
    }
}
