using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using InABox.Core; namespace InABox.Clients { public abstract class BaseClient : IClient where TEntity : Entity, new() { public bool ExcludeCustomProperties { get; set; } public TimeSpan Timeout { get; set; } = new TimeSpan(0, 1, 0); public abstract IEnumerable SupportedTypes(); public abstract bool IsConnected(); public event LogEvent? OnLog; protected void RaiseLogEvent(LogType type, String userid, string format, Guid transaction) => OnLog?.Invoke(type, userid, format, transaction); #region Validation public virtual IValidationData Validate(string userid, string password, Guid session) { return DoValidate(userid, password, session); } protected abstract IValidationData DoValidate(string userid, string password, Guid session = default); public virtual IValidationData Validate(string pin, Guid session) { return DoValidate(pin, session); } protected abstract IValidationData DoValidate(string pin, Guid session = default); public virtual IValidationData Validate(Guid session) { return DoValidate(session); } protected abstract IValidationData DoValidate(Guid session = default); #endregion #region Query public CoreTable Query(object? filter = null, object? columns = null, object? sort = null, CoreRange? range = null) { return DoQuery((Filter?)filter, (Columns?)columns, (SortOrder?)sort, range); } public CoreTable Query(IFilter? filter = null, IColumns? columns = null, ISortOrder? sort = null, CoreRange? range = null) { return DoQuery((Filter?)filter, (Columns?)columns, (SortOrder?)sort, range); } public CoreTable Query(Filter? filter = null, Columns? columns = null, SortOrder? sort = null, CoreRange? range = null) { return DoQuery(filter, columns, sort, range); } public void Query(Filter? filter, Columns? columns, SortOrder? sort, CoreRange? range, Action callback) { Task.Run(() => { Exception? err = null; CoreTable? result = null; try { result = DoQuery(filter, columns, sort, range); } catch (Exception e) { err = e; } finally { callback.Invoke(result, err); } }); } protected abstract CoreTable DoQuery(Filter? filter, Columns? columns, SortOrder? sort = null, CoreRange? range = null); #endregion #region Load public Entity[] Load(object? filter = null, object? sort = null, CoreRange? range = null) { return DoLoad( (Filter?)filter, (SortOrder?)sort, range ).OfType() .ToArray(); } public TEntity[] Load(Filter? filter = null, SortOrder? sort = null, CoreRange? range = null) { return DoLoad(filter, sort, range); } public void Load(Filter? filter, SortOrder? sort, CoreRange? range, Action callback) { Task.Run(() => { Exception? err = null; TEntity[]? result = null; try { result = DoLoad(filter, sort, range); } catch (Exception e) { err = e; } finally { callback.Invoke(result, err); } }); } protected abstract TEntity[] DoLoad(Filter? filter = null, SortOrder? sort = null, CoreRange? range = null); #endregion #region Save public void Save(object entity, string auditnote) { var e = (TEntity)entity; DoSave(e, auditnote); } public void Save(IEnumerable entities, string auditnote) { var items = entities.Select(x => (TEntity)x); DoSave(items, auditnote); } public void Save(TEntity entity, string auditnote) { DoSave(entity, auditnote); } public void Save(IEnumerable entities, string auditnote) { DoSave(entities, auditnote); } public void Save(TEntity entity, string auditnote, Action callback) { Task.Run(() => { Exception? err = null; try { DoSave(entity, auditnote); } catch (Exception e) { err = e; } finally { callback.Invoke(entity, err); } }); } public void Save(IEnumerable entities, string auditnote, Action, Exception?> callback) { Task.Run(() => { Exception? err = null; var items = entities.AsArray(); try { DoSave(items, auditnote); } catch (Exception e) { err = e; } finally { callback.Invoke(items, err); } }); } protected abstract void DoSave(TEntity entity, string auditnote); protected abstract void DoSave(IEnumerable entities, string auditnote); #endregion #region Delete public void Delete(object entity, string auditnote) { DoDelete((TEntity)entity, auditnote); } public void Delete(IEnumerable entities, string auditnote) { var items = entities.Select(x => (TEntity)x).ToList(); DoDelete(items, auditnote); } public void Delete(TEntity entity, string auditnote) { DoDelete(entity, auditnote); } public void Delete(IEnumerable entities, string auditnote) { DoDelete(entities, auditnote); } public void Delete(TEntity entity, string auditnote, Action callback) { Task.Run(() => { Exception? err = null; try { DoDelete(entity, auditnote); } catch (Exception e) { err = e; } finally { callback.Invoke(entity, err); } } ); } public void Delete(IEnumerable entities, string auditnote, Action, Exception?> callback) { Task.Run(() => { Exception? err = null; var items = entities.ToArray(); try { DoDelete(items, auditnote); } catch (Exception e) { err = e; } finally { callback.Invoke(items, err); } }); } protected abstract void DoDelete(TEntity entity, string auditnote); protected abstract void DoDelete(IEnumerable entities, string auditnote); #endregion #region MultipleTables public Dictionary QueryMultiple(Dictionary queries) { if(queries.Count == 0) { return new Dictionary(); } else { return DoQueryMultiple(queries); } } protected abstract Dictionary DoQueryMultiple(Dictionary queries); public void QueryMultiple(Action?, Exception?> callback, Dictionary queries) { Task.Run(() => { Exception? err = null; Dictionary? result = null; try { result = QueryMultiple(queries); } catch (Exception e) { err = e; } finally { callback.Invoke(result, err); } }); } #endregion #region 2FA public bool Check2FA(string code, Guid? session) { return DoCheck2FA(code, session); } protected abstract bool DoCheck2FA(string code, Guid? session); #endregion #region Ping public bool Ping() { return DoPing(); } protected abstract bool DoPing(); #endregion #region Info public abstract DatabaseInfo? Info(); #endregion #region Update public abstract string Version(); public abstract string ReleaseNotes(); public abstract byte[]? Installer(); #endregion } }