using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Settings;
using TINK.Model.User.Account;
using TINK.Model.Settings;
using TINK.Model.Logging;
using Serilog.Events;
using Serilog.Core;
using Serilog;
using Plugin.Connectivity;
using System.Threading;
using TINK.Services.BluetoothLock;
using TINK.Model.Services.Geolocation;
using TINK.Model.Services.CopriApi.ServerUris;
using TINK.Services.BluetoothLock.Crypto;
using TINK.ViewModel.Map;
using TINK.ViewModel.Settings;
using TINK.Services;
using TINK.Services.BluetoothLock.BLE;
using Xamarin.Forms;
using TINK.Model.Station;
namespace TINK.Model
{
[DataContract]
public class TinkApp : ITinkApp
{
/// Delegate used by login view to commit user name and password.
/// Mail address used as id login.
/// Password for login.
/// True if setting credentials succeeded.
public delegate bool SetCredentialsDelegate(string p_strMailAddress, string p_strPassword);
/// Returns the id of the app (sharee.bike) to be identified by copri.
public static string MerchantId => "oiF2kahH";
///
/// Holds status about whants new page.
///
public WhatsNew WhatsNew { get; private set; }
/// Sets flag whats new page was already shown to true.
public void SetWhatsNewWasShown() => WhatsNew = WhatsNew.SetWasShown();
/// Holds uris of copri servers.
public CopriServerUriList Uris { get; }
/// Holds the filters loaded from settings.
public IGroupFilterSettings FilterGroupSetting { get; set; }
/// Holds the filter which is applied on the map view. Either TINK or Konrad stations are displayed.
private IGroupFilterMapPage m_oFilterDictionaryMapPage;
/// Holds the filter which is applied on the map view. Either TINK or Konrad stations are displayed.
public IGroupFilterMapPage GroupFilterMapPage
{
get => m_oFilterDictionaryMapPage;
set => m_oFilterDictionaryMapPage = value ?? new GroupFilterMapPage();
}
/// Value indicating whether map is centerted to current position or not.
public bool CenterMapToCurrentLocation { get; set; }
/// Gets the minimum logging level.
public LogEventLevel MinimumLogEventLevel { get; set; }
/// Gets a value indicating whether reporting level is verbose or not.
public bool IsReportLevelVerbose { get; set; }
/// Holds the uri which is applied after restart.
public Uri NextActiveUri { get; set; }
/// Saves object to file.
public void Save()
=> JsonSettingsDictionary.Serialize(
SettingsFileFolder,
new Dictionary()
.SetGroupFilterMapPage(GroupFilterMapPage)
.SetCopriHostUri(NextActiveUri.AbsoluteUri)
.SetPollingParameters(Polling)
.SetGroupFilterSettings(FilterGroupSetting)
.SetAppVersion(AppVersion)
.SetMinimumLoggingLevel(MinimumLogEventLevel)
.SetIsReportLevelVerbose(IsReportLevelVerbose)
.SetExpiresAfter(ExpiresAfter)
.SetWhatsNew(AppVersion)
.SetActiveLockService(LocksServices.Active.GetType().FullName)
.SetActiveGeolocationService(GeolocationServices.Active.GetType().FullName)
.SetCenterMapToCurrentLocation(CenterMapToCurrentLocation)
.SetLogToExternalFolder(LogToExternalFolder)
.SetConnectTimeout(LocksServices.Active.TimeOut.MultiConnect)
.SetIsSiteCachingOn(IsSiteCachingOn)
.SetActiveTheme(Themes.Active.GetType().FullName));
///
/// Update connector from filters when
/// - login state changes
/// - view is toggled (TINK to Kornrad and vice versa)
///
public void UpdateConnector()
{
// Create filtered connector.
m_oConnector = FilteredConnectorFactory.Create(
FilterGroupSetting.DoFilter(ActiveUser.DoFilter(GroupFilterMapPage.DoFilter())),
m_oConnector.Connector);
}
/// Polling periode.
public PollingParameters Polling { get; set; }
public TimeSpan ExpiresAfter { get; set; }
/// Holds the version of the app.
public Version AppVersion { get; }
///
/// Holds the default polling value.
///
#if USCSHARP9
public TimeSpan DefaultPolling => new (0, 0, 10);
#else
public TimeSpan DefaultPolling => new TimeSpan(0, 0, 10);
#endif
/// Constructs TinkApp object.
///
///
///
///
/// Null in productive context. Service to querry geoloation for testing purposes. Parameter can be made optional.
/// Null in productive context. Service to control locks/ get locks information for testing proposes. Parameter can be made optional.
/// Object allowing platform specific operations.
///
///
/// True if connector has access to copri server, false if cached values are used.
/// Version of the app. If null version is set to a fixed dummy value (3.0.122) for testing purposes.
/// Version of app which was used before this session.
/// Holds
/// - the version when whats new info was shown last or
/// - version of application used last if whats new functionality was not implemented in this version or
/// - null if app is installed for the first time.
/// ///
public TinkApp(
Settings.Settings settings,
IStore accountStore,
Func connectorFactory,
IServicesContainer geolocationServicesContainer,
ILocksService locksService,
ISmartDevice device,
ISpecialFolder specialFolder,
ICipher cipher,
object arendiCentral = null,
Func isConnectedFunc = null,
Action postAction = null,
Version currentVersion = null,
Version lastVersion = null,
Version whatsNewShownInVersion = null)
{
PostAction = postAction
?? ((d, obj) => d(obj));
ConnectorFactory = connectorFactory
?? throw new ArgumentException("Can not instantiate TinkApp- object. No connector factory object available.");
Cipher = cipher ?? new Cipher();
var locksServices = locksService != null
? new HashSet { locksService }
: new HashSet {
new LockItByScanServiceEventBased(Cipher),
new LockItByScanServicePolling(Cipher),
new LockItByGuidService(Cipher),
#if BLUETOOTHLE // Requires LockItBluetoothle library.
new Bluetoothle.LockItByGuidService(Cipher),
#endif
#if ARENDI // Requires LockItArendi library.
new Arendi.LockItByGuidService(Cipher, arendiCentral),
new Arendi.LockItByScanService(Cipher, arendiCentral),
#endif
new LocksServiceInReach(),
new LocksServiceOutOfReach(),
};
LocksServices = new LocksServicesContainerMutable(
lastVersion >= new Version(3, 0, 173) ? settings.ActiveLockService : LocksServicesContainerMutable.DefaultLocksservice,
locksServices);
LocksServices.SetTimeOut(settings.ConnectTimeout);
Themes = new ServicesContainerMutable