using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySqlConnector;
using skyscraper8.Skyscraper.Scraper.Storage;

namespace skyscraper5.Data.MySql
{
    public partial class MySqlDataStorage : DataStorage
    {
        private struct TdtCoordinate
        {
            public int CurrentNetworkId { get; }
            public int CurrentTransportStreamId { get; }

            public TdtCoordinate(int currentNetworkId, int currentTransportStreamId)
            {
                CurrentNetworkId = currentNetworkId;
                CurrentTransportStreamId = currentTransportStreamId;
                CoordinateTimestamp = DateTime.MinValue;
            }

            public bool Equals(TdtCoordinate other)
            {
                return CurrentNetworkId == other.CurrentNetworkId && CurrentTransportStreamId == other.CurrentTransportStreamId;
            }

            public override bool Equals(object obj)
            {
                return obj is TdtCoordinate other && Equals(other);
            }

            public override int GetHashCode()
            {
                return HashCode.Combine(CurrentNetworkId, CurrentTransportStreamId);
            }

            public DateTime CoordinateTimestamp { get; set; }
        }

        private HashSet<TdtCoordinate> _tdtCoordinates;
        private DateTime? TestForTdt(MySqlConnection connection, int currentNetworkId, int currentTransportStreamId)
        {
            if (_tdtCoordinates == null)
                _tdtCoordinates = new HashSet<TdtCoordinate>();
            TdtCoordinate coordinate = new TdtCoordinate(currentNetworkId, currentTransportStreamId);
            TdtCoordinate storedCoordinate;
            bool hasStoredCoordinate = _tdtCoordinates.TryGetValue(coordinate, out storedCoordinate);
            if (hasStoredCoordinate)
                return storedCoordinate.CoordinateTimestamp;

            MySqlCommand mySqlCommand = connection.CreateCommand();
            mySqlCommand.CommandText = "SELECT utc FROM dvb_tdt WHERE cnid = @cnid AND ctid = @ctid";
            mySqlCommand.Parameters.AddWithValue("@cnid", currentNetworkId);
            mySqlCommand.Parameters.AddWithValue("@ctid", currentTransportStreamId);
            MySqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
            DateTime? result = null;
            if (mySqlDataReader.Read())
            {
                result = mySqlDataReader.GetDateTime(0);
                coordinate.CoordinateTimestamp = result.Value;
                _tdtCoordinates.Add(coordinate);
            }
            mySqlDataReader.Close();
            return result;
        }

        private void UpdateTdt(MySqlConnection connection, int currentNetworkId, int currentTransportStreamId, DateTime utcTime)
        {
            if (_speedhackQueue.Any(x => x.Key == SpeedhackType.UpdateTdt && (int)x.Value[0] == currentNetworkId && (int)x.Value[1] == currentTransportStreamId && (DateTime)x.Value[2] > utcTime))
            {
                return;
            }
            MySqlCommand mySqlCommand = connection.CreateCommand();
            mySqlCommand.CommandText =
                "UPDATE dvb_tdt SET utc = @utc, dateupdated = CURRENT_TIMESTAMP, num_updates = num_updates + 1 WHERE cnid = @cnid AND ctid = @ctid";
            mySqlCommand.Parameters.AddWithValue("@cnid", currentNetworkId);
            mySqlCommand.Parameters.AddWithValue("@ctid", currentTransportStreamId);
            mySqlCommand.Parameters.AddWithValue("@utc", utcTime);
            mySqlCommand.ExecuteNonQuery();
        }

        private void InsertTdt(MySqlConnection connection, int currentNetworkId, int currentTransportStreamId, DateTime utcTime)
        {
            MySqlCommand mySqlCommand = connection.CreateCommand();
            mySqlCommand.CommandText = "INSERT INTO dvb_tdt (cnid, ctid, utc) VALUES (@cnid, @ctid, @utc)";
            mySqlCommand.Parameters.AddWithValue("@cnid", currentNetworkId);
            mySqlCommand.Parameters.AddWithValue("@ctid", currentTransportStreamId);
            mySqlCommand.Parameters.AddWithValue("@utc", utcTime);
            mySqlCommand.ExecuteNonQuery();
        }

		public bool UpdateTimeAndDate(int currentNetworkId, int currentTransportStreamId, DateTime utcTime)
		{
			using (MySqlConnection connection = new MySqlConnection(_mcsb.ToString()))
			{
				bool result = false;
				connection.Open();
				DateTime? older = TestForTdt(connection, currentNetworkId, currentTransportStreamId);
				connection.Close();
				if (older.HasValue)
				{
					if (utcTime > older.Value)
					{
						//UpdateTdt(connection, currentNetworkId, currentTransportStreamId, utcTime);
						EnqueueSpeedhack(SpeedhackType.UpdateTdt, currentNetworkId, currentTransportStreamId, utcTime);
						result = true;
					}
				}
				else
				{
					//InsertTdt(connection, currentNetworkId, currentTransportStreamId, utcTime);
					EnqueueSpeedhack(SpeedhackType.InsertTdt, currentNetworkId, currentTransportStreamId, utcTime);
					_tdtCoordinates.Add(new TdtCoordinate(currentNetworkId, currentTransportStreamId));
					result = true;
				}
				return result;
			}
		}

	}
}
