using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Serilog.Events; using TINK.Model.Services.CopriApi.ServerUris; using TINK.Services.BluetoothLock; using TINK.Services.Geolocation; using TINK.Settings; using TINK.ViewModel.Map; using TINK.ViewModel.Settings; namespace TINK.Model.Settings { public static class JsonSettingsDictionary { /// Title of the settings file. public const string SETTINGSFILETITLE = "Setting.Json"; /// Key of the app version entry. public const string APPVERSIONKEY = "AppVersion"; /// Key of the app version entry. public const string SHOWWHATSNEWKEY = "ShowWhatsNew"; /// Key of the app version entry. public const string EXPIRESAFTER = "ExpiresAfter"; /// Key of the connect timeout. public const string CONNECTTIMEOUT = "ConnectTimeout"; /// Key of the logging level entry. public const string MINLOGGINGLEVELKEY = "MinimumLoggingLevel"; /// Key of the logging level entry. public const string ISREPORTLEVELVERBOSEKEY = "IsReportLevelVerbose"; /// Key of the center to ... entry. public const string CENTERMAPTOCURRENTLOCATION = "CenterMapToCurrentLocation"; /// Key of the center to ... entry. public const string STARTUPSETTINGS = "StartupSettings"; public const string LOGTOEXTERNALFOLDER = "LogToExternalFolder"; public const string THEMEKEY = "Theme"; public const string ISSITECACHINGON = "IsSiteCachingOn"; /// Gets a nullable value. /// Dictionary to get value from. public static T? GetNullableEntry( string keyName, IDictionary settingsJSON) where T : struct { if (!settingsJSON.TryGetValue(keyName, out string boolText) || string.IsNullOrEmpty(boolText)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(boolText); } /// Gets a value to type class. /// Dictionary to get value from. public static T GetEntry( string keyName, IDictionary settingsJSON, Func legacyValueConverter = null) where T : class { if (string.IsNullOrEmpty(keyName) || settingsJSON == null || !settingsJSON.TryGetValue(keyName, out string valueJSON) || string.IsNullOrEmpty(valueJSON)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(legacyValueConverter != null ? legacyValueConverter(valueJSON) : valueJSON); } /// Sets a nullable. /// Entry to add to dictionary. /// Key to use for value. /// Dictionary to set value to. public static Dictionary SetEntry(T entry, string keyName, IDictionary targetDictionary) { // Set value. if (targetDictionary == null) throw new Exception($"Writing entry value {keyName} to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { keyName, JsonConvert.SerializeObject(entry) } }).ToDictionary(key => key.Key, value => value.Value); } /// Sets the timeout to apply when connecting to bluetooth lock. /// Dictionary to write information to. /// Connect timeout value. public static Dictionary SetConnectTimeout( this IDictionary targetDictionary, TimeSpan connectTimeout) { if (targetDictionary == null) throw new Exception("Writing conntect timeout info failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { CONNECTTIMEOUT, JsonConvert.SerializeObject(connectTimeout, new JavaScriptDateTimeConverter()) } }).ToDictionary(key => key.Key, value => value.Value); } /// Sets the uri of the active copri host. /// Dictionary holding parameters from JSON. public static Dictionary SetCopriHostUri(this IDictionary targetDictionary, string p_strNextActiveUriText) { if (targetDictionary == null) throw new Exception("Writing copri host uri to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { typeof(CopriServerUriList).ToString(), JsonConvert.SerializeObject(p_strNextActiveUriText) }, }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the timeout to apply when connecting to bluetooth lock. /// Dictionary to get information from. /// Connect timeout value. public static TimeSpan? GetConnectTimeout(Dictionary settingsJSON) { if (!settingsJSON.TryGetValue(CONNECTTIMEOUT, out string connectTimeout) || string.IsNullOrEmpty(connectTimeout)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(connectTimeout, new JavaScriptDateTimeConverter()); } /// Gets the logging level. /// Dictionary to get logging level from. /// Logging level public static Uri GetCopriHostUri(this IDictionary settingsJSON) { // Get uri of copri server. if (!settingsJSON.TryGetValue(typeof(CopriServerUriList).ToString(), out string uriText) || string.IsNullOrEmpty(uriText)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(uriText); } /// Sets the version of the app. /// Dictionary holding parameters from JSON. public static Dictionary SetAppVersion( this IDictionary targetDictionary, Version appVersion) { if (targetDictionary == null) throw new Exception("Writing app version to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { {APPVERSIONKEY , JsonConvert.SerializeObject(appVersion, new VersionConverter()) }, }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the app versions. /// Dictionary to get logging level from. /// Logging level public static Version GetAppVersion(this IDictionary settingsJSON) { // Get the version of the app which wrote the settings file. if (!settingsJSON.TryGetValue(APPVERSIONKEY, out string appVersion) || string.IsNullOrEmpty(appVersion)) { // File holds no entry. return null; } return appVersion.TrimStart().StartsWith("\"") ? JsonConvert.DeserializeObject(appVersion, new VersionConverter()) : Version.Parse(appVersion); // Format used up to version 3.0.0.115 } /// Sets whether polling is on or off and the period if polling is on. /// Dictionary to write entries to. public static Dictionary SetPollingParameters( this IDictionary targetDictionary, PollingParameters pollingParameter) { if (targetDictionary == null) throw new Exception("Writing polling parameters to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { $"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", JsonConvert.SerializeObject(pollingParameter.Periode) }, { $"{typeof(PollingParameters).Name}_{typeof(bool).Name}", JsonConvert.SerializeObject(pollingParameter.IsActivated) }, }).ToDictionary(key => key.Key, value => value.Value); } /// Get whether polling is on or off and the period if polling is on. /// Dictionary holding parameters from JSON. /// Polling parameters. public static PollingParameters GetPollingParameters(this IDictionary settingsJSON) { // Check if dictionary contains entry for period. if (settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", out string period) && settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(bool).Name}", out string active) && !string.IsNullOrEmpty(period) && !string.IsNullOrEmpty(active)) { return new PollingParameters( JsonConvert.DeserializeObject(period), JsonConvert.DeserializeObject(active)); } return null; } /// Saves object to file. /// Settings to save. public static void Serialize(string settingsFileFolder, IDictionary settingsList) { // Save settings to file. var l_oText = JsonConvert.SerializeObject(settingsList, Formatting.Indented); var l_oFolder = settingsFileFolder; System.IO.File.WriteAllText($"{l_oFolder}{System.IO.Path.DirectorySeparatorChar}{SETTINGSFILETITLE}", l_oText); } /// Gets TINK app settings form xml- file. /// Directory to read settings from. /// Dictionary of settings. public static Dictionary Deserialize(string settingsDirectory) { var fileName = $"{settingsDirectory}{System.IO.Path.DirectorySeparatorChar}{SETTINGSFILETITLE}"; if (!System.IO.File.Exists(fileName)) { // File is empty. Nothing to read. return new Dictionary(); ; } var jsonFile = System.IO.File.ReadAllText(fileName); if (string.IsNullOrEmpty(jsonFile)) { // File is empty. Nothing to read. return new Dictionary(); } // Load setting file. return JsonConvert.DeserializeObject>(jsonFile); } /// Gets the logging level. /// Dictionary to get logging level from. /// Logging level. public static LogEventLevel? GetMinimumLoggingLevel( Dictionary settingsJSON) { // Get logging level. if (!settingsJSON.TryGetValue(MINLOGGINGLEVELKEY, out string level) || string.IsNullOrEmpty(level)) { // File holds no entry. return null; } return (LogEventLevel)int.Parse(JsonConvert.DeserializeObject(level)); } /// Gets a value indicating whether report level is verbose or not. /// Dictionary to get value from. public static bool? GetIsReportLevelVerbose(Dictionary settingsJSON) => GetNullableEntry(ISREPORTLEVELVERBOSEKEY, settingsJSON); /// Sets a value indicating whether report level is verbose or not. /// Dictionary to get value from. public static Dictionary SetIsReportLevelVerbose(this IDictionary targetDictionary, bool isReportLevelVerbose) => SetEntry(isReportLevelVerbose, ISREPORTLEVELVERBOSEKEY, targetDictionary); /// Sets the logging level. /// Dictionary to get logging level from. public static Dictionary SetMinimumLoggingLevel(this IDictionary targetDictionary, LogEventLevel level) { // Set logging level. if (targetDictionary == null) throw new Exception("Writing logging level to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { MINLOGGINGLEVELKEY, JsonConvert.SerializeObject((int)level) } }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the version of app when whats new was shown. /// Dictionary to get logging level from. /// Version of the app. public static Version GetWhatsNew(Dictionary settingsJSON) { // Get logging level. if (!settingsJSON.TryGetValue(SHOWWHATSNEWKEY, out string whatsNewVersion) || string.IsNullOrEmpty(whatsNewVersion)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(whatsNewVersion, new VersionConverter()); } /// Sets the version of app when whats new was shown. /// Dictionary to get information from. public static Dictionary SetWhatsNew(this IDictionary targetDictionary, Version appVersion) { // Set logging level. if (targetDictionary == null) throw new Exception("Writing WhatsNew info failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { SHOWWHATSNEWKEY, JsonConvert.SerializeObject(appVersion, new VersionConverter()) } }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the expires after value. /// Dictionary to get expries after value from. /// Expires after value. public static TimeSpan? GetExpiresAfter(Dictionary settingsJSON) { if (!settingsJSON.TryGetValue(EXPIRESAFTER, out string expiresAfter) || string.IsNullOrEmpty(expiresAfter)) { // File holds no entry. return null; } return JsonConvert.DeserializeObject(expiresAfter, new JavaScriptDateTimeConverter()); } /// Sets the the expiration time. /// Dictionary to write information to. public static Dictionary SetExpiresAfter(this IDictionary targetDictionary, TimeSpan expiresAfter) { if (targetDictionary == null) throw new Exception("Writing ExpiresAfter info failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { EXPIRESAFTER, JsonConvert.SerializeObject(expiresAfter, new JavaScriptDateTimeConverter()) } }).ToDictionary(key => key.Key, value => value.Value); } /// Sets the active lock service name. /// Dictionary holding parameters from JSON. public static Dictionary SetActiveLockService(this IDictionary targetDictionary, string activeLockService) { if (targetDictionary == null) throw new Exception("Writing active lock service name to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { typeof(ILocksService).Name, activeLockService }, }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the active lock service name. /// Dictionary to get logging level from. /// Active lock service name. public static string GetActiveLockService(this IDictionary settingsJSON) { // Get uri of copri server. if (!settingsJSON.TryGetValue(typeof(ILocksService).Name, out string activeLockService) || string.IsNullOrEmpty(activeLockService)) { // File holds no entry. return null; } if (activeLockService == "TINK.Services.BluetoothLock.BLE.LockItByScanService") { // Name of this service was switched. return typeof(TINK.Services.BluetoothLock.BLE.LockItByScanServicePolling).FullName; } return activeLockService; } /// Sets the active Geolocation service name. /// Dictionary holding parameters from JSON. public static Dictionary SetActiveGeolocationService( this IDictionary targetDictionary, string activeGeolocationService) { if (targetDictionary == null) throw new Exception("Writing active geolocation service name to dictionary failed. Dictionary must not be null."); return targetDictionary.Union(new Dictionary { { typeof(IGeolocationService).Name, activeGeolocationService }, }).ToDictionary(key => key.Key, value => value.Value); } /// Gets the active Geolocation service name. /// Dictionary to get name of geolocation service from. /// Active lock service name. public static string GetActiveGeolocationService(this IDictionary settingsJSON) { // Get uri of copri server. if (!settingsJSON.TryGetValue(typeof(IGeolocationService).Name, out string activeGeolocationService) || string.IsNullOrEmpty(activeGeolocationService)) { // File holds no entry. return null; } return activeGeolocationService; } /// Gets a value indicating whether to center the map to location or not. /// Dictionary to get value from. public static bool? GetCenterMapToCurrentLocation(Dictionary settingsJSON) => GetNullableEntry(CENTERMAPTOCURRENTLOCATION, settingsJSON); /// Sets a value indicating whether to center the map to location or not. /// Dictionary to get value from. public static Dictionary SetCenterMapToCurrentLocation(this IDictionary targetDictionary, bool centerMapToCurrentLocation) => SetEntry(centerMapToCurrentLocation, CENTERMAPTOCURRENTLOCATION, targetDictionary); /// Gets whether to store logging data on SD card or not. /// Dictionary to get value from. public static bool? GetLogToExternalFolder(Dictionary settingsJSON) => GetNullableEntry(LOGTOEXTERNALFOLDER, settingsJSON); /// Gets full class name of active theme. /// Dictionary to get value from. public static string GetActiveTheme(Dictionary settingsJSON) => GetEntry(THEMEKEY, settingsJSON, (value) => { if (value == JsonConvert.SerializeObject(typeof(Themes.Konrad).FullName)) { return JsonConvert.SerializeObject(TINK.Services.ThemeNS.ThemeSet.Konrad.ToString()); } else if (value == JsonConvert.SerializeObject(typeof(Themes.LastenradBayern).FullName)) { return JsonConvert.SerializeObject(TINK.Services.ThemeNS.ThemeSet.LastenradBayern.ToString()); } else if (value == JsonConvert.SerializeObject(typeof(Themes.ShareeBike).FullName)) { return JsonConvert.SerializeObject(TINK.Services.ThemeNS.ThemeSet.ShareeBike.ToString()); } else { return value; } }); /// Gets a value indicating whether site caching is on or off. /// Dictionary to get value from. public static bool? GetIsSiteCachingOn(Dictionary settingsJSON) => GetNullableEntry(ISSITECACHINGON, settingsJSON); /// Sets whether to store logging data on SD card or not. /// Dictionary to write value to. public static Dictionary SetLogToExternalFolder(this IDictionary targetDictionary, bool useSdCard) => SetEntry(useSdCard, LOGTOEXTERNALFOLDER, targetDictionary); /// Sets active theme. /// Dictionary to set value to. public static Dictionary SetActiveTheme( this IDictionary targetDictionary, string theme) => SetEntry(theme, THEMEKEY, targetDictionary); /// Sets whether site caching is on or off. /// Dictionary to get value from. public static Dictionary SetIsSiteCachingOn(this IDictionary targetDictionary, bool useSdCard) => SetEntry(useSdCard, ISSITECACHINGON, targetDictionary); /// Gets the map page filter. /// Settings objet to load from. public static IGroupFilterMapPage GetGroupFilterMapPage(this IDictionary settings) { var keyName = "FilterCollection_MapPageFilter"; if (settings == null || !settings.ContainsKey(keyName)) { return null; } return new GroupFilterMapPage(JsonConvert.DeserializeObject>(settings[keyName])); } public static IDictionary SetGroupFilterMapPage( this IDictionary settings, IDictionary filterCollection) { if (settings == null || filterCollection == null || filterCollection.Count < 1) { return settings; } settings["FilterCollection_MapPageFilter"] = JsonConvert.SerializeObject(filterCollection); return settings; } /// Gets the settings filter. /// Settings objet to load from. public static IGroupFilterSettings GetGoupFilterSettings(this IDictionary settings) { var keyName = "FilterCollection"; if (settings == null || !settings.ContainsKey(keyName)) { return null; } var legacyFilterCollection = new GroupFilterSettings(JsonConvert.DeserializeObject>(settings[keyName])); // Process legacy entries. var updatedFilterCollection = legacyFilterCollection.Where(x => x.Key.ToUpper() != "TINK.SMS" && x.Key.ToUpper() != "TINK.COPRI").ToDictionary(x => x.Key, x => x.Value); if (legacyFilterCollection.Count() <= updatedFilterCollection.Count()) { // No legacy entries "INK.SMS" or "TINK.COPRI" found. return legacyFilterCollection; } var list = updatedFilterCollection.ToList(); updatedFilterCollection.Add( "TINK", legacyFilterCollection.Any(x => x.Key.ToUpper() == "TINK.COPRI") ? legacyFilterCollection.FirstOrDefault(x => x.Key.ToUpper() == "TINK.COPRI").Value : FilterState.Off); return new GroupFilterSettings(updatedFilterCollection); } public static IDictionary SetGroupFilterSettings( this IDictionary settings, IDictionary filterCollection) { if (settings == null || filterCollection == null || filterCollection.Count < 1) { return settings; } settings["FilterCollection"] = JsonConvert.SerializeObject(filterCollection); return settings; } /// /// Gets the startup settings from dictionary. /// /// Settings objet to load from. public static StartupSettings GetStartupSettings(this IDictionary settingsJSON) => GetEntry(STARTUPSETTINGS, settingsJSON) ?? new StartupSettings(); /// Sets the startup settings. /// Dictionary to write value to. public static IDictionary SetStartupSettings( this IDictionary settingsJSON, IStartupSettings startupSettings) { if (settingsJSON == null || startupSettings == null) { return settingsJSON; } settingsJSON[STARTUPSETTINGS] = JsonConvert.SerializeObject(startupSettings); return settingsJSON; } } }