using Microsoft.Data.SqlClient; using System.Collections.Concurrent; using System.Data; using System.Threading.Tasks; using Telerik.Windows.Documents.Fixed.Model.Editing.Lists; using Telerik.Windows.Documents.Fixed.Model.Navigation; using XAct; namespace TireTargets.Components.CSharp { public class DatabaseDriver : IDisposable { private bool disposedValue; private ConcurrentBag _tasks = new ConcurrentBag(); private bool isExiting = false; private static string _connectionString = "Server=BigMac; Database=TireTargets; Integrated Security=SSPI;MultipleActiveResultSets=True;TrustServerCertificate=True;"; protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { isExiting = true; Task.WaitAll(_tasks.ToArray()); } disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public static async Task SignIn(string platform, string id, string fname, string email) { try { using (var cn = new SqlConnection(_connectionString)) { await cn.OpenAsync(); await using var queryCmd = new SqlCommand(String.Format("SELECT COUNT(UniqID) FROM [dbo].[User] WHERE {0}ID = '{1}'", platform, id), cn); await using var rd = await queryCmd.ExecuteReaderAsync(); // Get number of occurences of this ID/Platform combo int count = -1; while (await rd.ReadAsync()) { count = rd.GetInt32(0); } if (count > 0) // If the account already exists, read from the DB for session info { } else // Otherwise, we need to create a new account { await using var insertCmd = new SqlCommand(String.Format("INSERT INTO [dbo].[User] ({0}ID, {0}Name, {0}Email) VALUES (@id, @fname, @email)", platform), cn); insertCmd.Parameters.AddWithValue("@id", id); insertCmd.Parameters.AddWithValue("@fname", fname); insertCmd.Parameters.AddWithValue("@email", email); insertCmd.ExecuteNonQuery(); } cn.Close(); } } catch (Exception ex) { Console.WriteLine(ex.Message); return false; } return true; } public static async Task> GetLocationInfoForUser(string id, string platform) { try { using (var cn = new SqlConnection(_connectionString)) { await cn.OpenAsync(); // Confirm that user has a valid location ID set string locQueryString = ""; if (platform == "Google") locQueryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [GoogleID] = '{0}'", id.Replace("'","''")); else if (platform == "FB") locQueryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [FBID] = '{0}'", id.Replace("'", "''")); await using var locQuery = new SqlCommand(locQueryString, cn); await using var locRd = await locQuery.ExecuteReaderAsync(); // Extract loc id int locationId = -1; while (await locRd.ReadAsync()) { locationId = locRd.GetInt32(0); } // Check if user's LocID is a RootID string rootString = String.Format("SELECT COUNT(*) FROM [dbo].[Location] WHERE RootID = {0}", ("" + locationId).Replace("'","''")); SqlCommand cmd = new SqlCommand(rootString, cn); Int32 val = (Int32)cmd.ExecuteScalar(); string locInfoString = ""; if (val > 1) { locInfoString = String.Format("SELECT * FROM [dbo].[Location] WHERE RootID = {0}", ("" + locationId).Replace("'", "''")); } else // Nothing matches { locInfoString = String.Format("SELECT * FROM [dbo].[Location] WHERE LocationID = {0}", ("" + locationId).Replace("'", "''")); } // Find the location in Location table await using var queryCmd = new SqlCommand(locInfoString, cn); await using var rd = await queryCmd.ExecuteReaderAsync(); // Extract loc id List locations = new List(); while (await rd.ReadAsync()) { var locID = rd.GetInt32(0); var rootID = rd.GetInt32(1); var locName = rd.GetString(2); var lastSelected = rd.GetDateTime(3); var needSelection = rd.GetInt32(4); var selectionJson = rd.GetString(5); var enabled = rd.GetInt32(6); Location current = new Location(locID, rootID, locName, lastSelected, needSelection, selectionJson, enabled); locations.Add(current); } cn.Close(); return locations; } } catch (Exception ex) { Console.WriteLine(ex.Message); } return new List(); } public static async Task<(DateTime, DateTime)> GetSelectionTimes() { using (var cn = new SqlConnection(_connectionString)) { await cn.OpenAsync(); await using var cmd = new SqlCommand("SELECT * FROM [cfg].[Selection]", cn); await using var rd = await cmd.ExecuteReaderAsync(); (DateTime, DateTime) selectionTime = (default, default); while (await rd.ReadAsync()) { selectionTime.Item1 = rd.GetDateTime(0); selectionTime.Item2 = rd.GetDateTime(1); } return selectionTime; } } public static async Task> DoesLocationNeedSelection() { // Determine if offers need to be selected var locInfo = await GetLocationInfoForUser(Layout.MainLayout.Session["id"], Layout.MainLayout.Session["login_method"]); var selectionTime = await GetSelectionTimes(); List<(int, bool)> results = new List<(int, bool)> (); foreach (Location current in locInfo) { // Location NeedSelection is effectively an override, forcing them to re-select for the flagged location(s) if (current.NeedSelection == 1 || (current.LastSelected < selectionTime.Item1 && DateTime.Now < selectionTime.Item2)) { results.Add((current.LocationID, true)); } else { results.Add((current.LocationID, false)); } } return results; } public static async Task DoesUserHaveLocation(string id, string platform) { using (var cn = new SqlConnection(_connectionString)) { await cn.OpenAsync(); string queryString = ""; if (platform == "Google") queryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [GoogleID] = '{0}'", id.Replace("'", "''")); else if (platform == "FB") queryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [FBID] = '{0}'", id.Replace("'", "''")); await using var cmd = new SqlCommand(queryString, cn); await using var rd = await cmd.ExecuteReaderAsync(); while (await rd.ReadAsync()) { if (rd.IsDBNull(0) || rd.GetInt32(0) == -1) return false; } return true; } } public static async Task UpdateSelection(Dictionary locSelections) { using (var cn = new SqlConnection(_connectionString)) { await cn.OpenAsync(); foreach (var current in locSelections) { var query = String.Format("UPDATE [dbo].[Location] SET [SelectionJson] = '{0}', [LastSelected] = GETDATE() WHERE LocationID = {1}", current.Value, current.Key); await using var cmd = new SqlCommand(query, cn); cmd.ExecuteNonQuery(); } } return true; } public class Location { public Location(int locID, int rootID, string locName, DateTime lastSelect, int needSelection, string selectionJson, int enabled) { LocationID = locID; RootID = rootID; LocationName = locName; LastSelected = lastSelect; NeedSelection = needSelection; SelectionJson = selectionJson; Enabled = enabled; } public int LocationID { get; set; } public int RootID { get; set; } public string LocationName { get; set; } public DateTime LastSelected { get; set; } public int NeedSelection { get; set; } public string SelectionJson { get; set; } public int Enabled { get; set; } } } }