using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace skyscraper5.Data.PostgreSql
{
    public partial class PostgresqlDataStore
    {
        private HashSet<Tuple<int, int, string>> _knownCompliances;
        public bool IsCompliant(int currentNetworkId, int currentTransportStreamId, string compliance)
        {
            if (_knownCompliances == null)
                _knownCompliances = new HashSet<Tuple<int, int, string>>();

            Tuple<int, int, string> key = new Tuple<int, int, string>(currentNetworkId, currentTransportStreamId, compliance);
            if (_knownCompliances.Contains(key))
                return true;

            bool result;
            using (NpgsqlConnection conn = new NpgsqlConnection(connectionStringBuilder.ToString()))
            {
                conn.Open();
                NpgsqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "SELECT dateadded FROM dvb_tsdt WHERE cnid = @cnid AND ctsid = @ctsid AND compliance = @compliance";
                cmd.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
                cmd.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
                cmd.Parameters.AddWithValue("@compliance", NpgsqlTypes.NpgsqlDbType.Text, compliance);
                NpgsqlDataReader reader = cmd.ExecuteReader();
                result = reader.Read();
                reader.Close();
                cmd.Dispose();
                conn.Close();
            }
            if (result)
                _knownCompliances.Add(key);
            return result;
        }

        public void MarkAsCompliant(int currentNetworkId, int currentTransportStreamId, string compliance)
        {
            EnqueueTask(x => InsertTsdt(x, currentNetworkId, currentTransportStreamId, compliance));
            Tuple<int, int, string> key = new Tuple<int, int, string>(currentNetworkId, currentTransportStreamId, compliance);
            _knownCompliances.Add(key);
        }

        private void InsertTsdt(NpgsqlConnection x, int currentNetworkId, int currentTransportStreamId, string compliance)
        {
            NpgsqlCommand cmd = x.CreateCommand();
            cmd.CommandText = "INSERT INTO dvb_tsdt (cnid,ctsid,compliance) VALUES (@cnid,@ctsid,@compliance)";
            cmd.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
            cmd.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
            cmd.Parameters.AddWithValue("@compliance", NpgsqlTypes.NpgsqlDbType.Text, compliance);
            cmd.ExecuteNonQuery();
        }

        private HashSet<Tuple<int, int, string>> knownStationIdentifications;
        public bool SetStationIdentification(int currentNetworkId, int currentTransportStreamId, string stationIdentification)
        {
            if (stationIdentification == null)
                return false;

            if (knownStationIdentifications == null)
                knownStationIdentifications = new HashSet<Tuple<int, int, string>>();

            Tuple<int, int, string> key = new Tuple<int, int, string>(currentNetworkId, currentTransportStreamId, stationIdentification);
            if (knownStationIdentifications.Contains(key))
                return false;

            string currentStationIdentification = null;
            using (NpgsqlConnection conn = new NpgsqlConnection(connectionStringBuilder.ToString()))
            {
                conn.Open();
                NpgsqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "SELECT station_identification FROM dvb_tsdt WHERE cnid = @cnid AND ctsid = @ctsid";
                cmd.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
                cmd.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
                NpgsqlDataReader reader = cmd.ExecuteReader();
                if (!reader.Read())
                {
                    //station identification without compliance? weird, let's wait a bit and try again.
                    reader.Close();
                    conn.Close();
                    return false;
                }
                if (!reader.IsDBNull(0))
                    currentStationIdentification = reader.GetString(0);
                reader.Close();
                cmd.Dispose();
                conn.Close();
            }

            if (stationIdentification.Equals(currentStationIdentification))
            {
                //schon bekannt, alles gut.
                knownStationIdentifications.Add(key);
                return false;
            }
            else
            {
                //irgendwie anders
                EnqueueTask(x => UpdateStationIdentification(x, currentNetworkId, currentTransportStreamId, stationIdentification));
                knownStationIdentifications.Add(key);
                return true;
            }
        }

        private void UpdateStationIdentification(NpgsqlConnection x, int currentNetworkId, int currentTransportStreamId, string stationIdentification)
        {
            NpgsqlCommand cmd = x.CreateCommand();
            cmd.CommandText = "update dvb_tsdt\r\n" +
                "set station_identification = @station_identification\r\n" +
                "where cnid = @cnid\r\n" +
                "and ctsid = @ctsid";
            cmd.Parameters.AddWithValue("@cnid", NpgsqlTypes.NpgsqlDbType.Integer, currentNetworkId);
            cmd.Parameters.AddWithValue("@ctsid", NpgsqlTypes.NpgsqlDbType.Integer, currentTransportStreamId);
            cmd.Parameters.AddWithValue("@station_identification", NpgsqlTypes.NpgsqlDbType.Text, stationIdentification);
            cmd.ExecuteNonQuery();
        }
    }
}
