using Npgsql;
using skyscraper5.Dvb.Psi.Model;
using skyscraper5.Skyscraper.Scraper.Storage.Utilities;
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<DatabaseKeyRst> _knownRsts;

        public bool StoreRunningStatus(uint transportStreamId, uint originalNetworkId, uint serviceId, uint eventId, RunningStatus runningStatus, DateTime currentTime)
        {
            if (_knownRsts == null)
                _knownRsts = new HashSet<DatabaseKeyRst>();

            DatabaseKeyRst key = new DatabaseKeyRst(transportStreamId, originalNetworkId, serviceId, eventId, runningStatus, currentTime);
            if (_knownRsts.Contains(key))
                return false;

            bool alreadyKnown;
            using (NpgsqlConnection conn = new NpgsqlConnection(connectionStringBuilder.ToString()))
            {
                conn.Open();
                NpgsqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "SELECT dateadded " +
                    "FROM dvb_rst " +
                    "WHERE tsid = @tsid " +
                    "AND onid = @onid " +
                    "AND sid = @sid " +
                    "AND eid = @eid " +
                    "AND running_status = @running_status " +
                    "AND dvb_time = @dvb_time";
                cmd.Parameters.AddWithValue("@tsid", NpgsqlTypes.NpgsqlDbType.Integer, (int)transportStreamId);
                cmd.Parameters.AddWithValue("@onid", NpgsqlTypes.NpgsqlDbType.Integer, (int)originalNetworkId);
                cmd.Parameters.AddWithValue("@sid", NpgsqlTypes.NpgsqlDbType.Integer, (int)serviceId);
                cmd.Parameters.AddWithValue("@eid", NpgsqlTypes.NpgsqlDbType.Integer, (int)eventId);
                cmd.Parameters.AddWithValue("@running_status", NpgsqlTypes.NpgsqlDbType.Integer, (int)runningStatus);
                cmd.Parameters.AddWithValue("@dvb_time", NpgsqlTypes.NpgsqlDbType.Timestamp, currentTime);
                NpgsqlDataReader dataReader = cmd.ExecuteReader();
                alreadyKnown = dataReader.Read();
                dataReader.Close();
                cmd.Dispose();
                conn.Close();
            }

            if (!alreadyKnown)
            {
                EnqueueTask(x => InsertRst(x, transportStreamId, originalNetworkId, serviceId, eventId, runningStatus, currentTime));
            }
            _knownRsts.Add(key);
            return !alreadyKnown;
        }

        private void InsertRst(NpgsqlConnection conn, uint transportStreamId, uint originalNetworkId, uint serviceId, uint eventId, RunningStatus runningStatus, DateTime currentTime)
        {
            NpgsqlCommand cmd = conn.CreateCommand();
            cmd.CommandText = "INSERT INTO dvb_rst (tsid, onid, sid, eid, running_status, dvb_time) VALUES (@tsid, @onid, @sid, @eid, @running_status, @dvb_time)";
            cmd.Parameters.AddWithValue("@tsid", NpgsqlTypes.NpgsqlDbType.Integer, (int)transportStreamId);
            cmd.Parameters.AddWithValue("@onid", NpgsqlTypes.NpgsqlDbType.Integer, (int)originalNetworkId);
            cmd.Parameters.AddWithValue("@sid", NpgsqlTypes.NpgsqlDbType.Integer, (int)serviceId);
            cmd.Parameters.AddWithValue("@eid", NpgsqlTypes.NpgsqlDbType.Integer, (int)eventId);
            cmd.Parameters.AddWithValue("@running_status", NpgsqlTypes.NpgsqlDbType.Integer, (int)runningStatus);
            cmd.Parameters.AddWithValue("@dvb_time", NpgsqlTypes.NpgsqlDbType.Timestamp, currentTime);
            cmd.ExecuteNonQuery();
            cmd.Dispose();
        }
    }
}
