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 APPVERIONKEY = "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";
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,
Dictionary 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,
Dictionary 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 p_oTargetDictionary, string p_strNextActiveUriText)
{
if (p_oTargetDictionary == null)
throw new Exception("Writing copri host uri to dictionary failed. Dictionary must not be null.");
return p_oTargetDictionary.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 corpi 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
{
{APPVERIONKEY , 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(APPVERIONKEY, 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 periode if polling is on.
/// Dictionary to write entries to.
public static Dictionary SetPollingParameters(this IDictionary p_oTargetDictionary, PollingParameters p_oPollingParameter)
{
if (p_oTargetDictionary == null)
throw new Exception("Writing polling parameters to dictionary failed. Dictionary must not be null.");
return p_oTargetDictionary.Union(new Dictionary
{
{ $"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", JsonConvert.SerializeObject(p_oPollingParameter.Periode) },
{ $"{typeof(PollingParameters).Name}_{typeof(bool).Name}", JsonConvert.SerializeObject(p_oPollingParameter.IsActivated) },
}).ToDictionary(key => key.Key, value => value.Value);
}
/// Get whether polling is on or off and the periode if polling is on.
/// Dictionary holding parameters from JSON.
/// Polling parameters.
public static PollingParameters GetPollingParameters(this IDictionary settingsJSON)
{
// Check if dictionary contains entry for periode.
if (settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", out string periode)
&& settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(bool).Name}", out string active)
&& !string.IsNullOrEmpty(periode)
&& !string.IsNullOrEmpty(active))
{
return new PollingParameters(
JsonConvert.DeserializeObject(periode),
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 l_oFileName = $"{settingsDirectory}{System.IO.Path.DirectorySeparatorChar}{SETTINGSFILETITLE}";
if (!System.IO.File.Exists(l_oFileName))
{
// File is empty. Nothing to read.
return new Dictionary(); ;
}
var l_oJSONFile = System.IO.File.ReadAllText(l_oFileName);
if (string.IsNullOrEmpty(l_oJSONFile))
{
// File is empty. Nothing to read.
return new Dictionary();
}
// Load setting file.
return JsonConvert.DeserializeObject>(l_oJSONFile);
}
/// 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 p_oTargetDictionary, LogEventLevel p_oLevel)
{
// Set logging level.
if (p_oTargetDictionary == null)
throw new Exception("Writing logging level to dictionary failed. Dictionary must not be null.");
return p_oTargetDictionary.Union(new Dictionary
{
{ MINLOGGINGLEVELKEY, JsonConvert.SerializeObject((int)p_oLevel) }
}).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 p_oTargetDictionary, Version p_oAppVersion)
{
// Set logging level.
if (p_oTargetDictionary == null)
throw new Exception("Writing WhatsNew info failed. Dictionary must not be null.");
return p_oTargetDictionary.Union(new Dictionary
{
{ SHOWWHATSNEWKEY, JsonConvert.SerializeObject(p_oAppVersion, 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 p_oTargetDictionary, TimeSpan expiresAfter)
{
if (p_oTargetDictionary == null)
throw new Exception("Writing ExpiresAfter info failed. Dictionary must not be null.");
return p_oTargetDictionary.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 corpi 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(IGeolocation).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 corpi server.
if (!settingsJSON.TryGetValue(typeof(IGeolocation).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 get value from.
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 p_oFilterCollection)
{
if (settings == null
|| p_oFilterCollection == null
|| p_oFilterCollection.Count < 1)
{
return settings;
}
settings["FilterCollection_MapPageFilter"] = JsonConvert.SerializeObject(p_oFilterCollection);
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 p_oFilterCollection)
{
if (settings == null
|| p_oFilterCollection == null
|| p_oFilterCollection.Count < 1)
{
return settings;
}
settings["FilterCollection"] = JsonConvert.SerializeObject(p_oFilterCollection);
return settings;
}
}
}