using gehGassiApp.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using gehGassiApp.Domain.Dogs;
using gehGassiApp.Core.Data;
using gehGassiApp.Core.Interfaces.Synchronization;
namespace gehGassiApp.Core.Services
{
///
/// Service der die Verwaltung von Hunderassen realisiert
///
public class DogRaceService : ServiceBase, IDogRaceService
{
private readonly ICommunicationService _communicationService;
private readonly ISyncInfoPullService _syncInfoPullService;
///
/// Erstellt eine Instanz
///
/// Instanz eines IUnitOfWork
/// Instanz eines ICommunicationService
/// Instanz eines ISyncInfoPullService
public DogRaceService(IUnitOfWork unitOfWork, ICommunicationService communicationService, ISyncInfoPullService syncInfoPullService) : base(unitOfWork)
{
_communicationService = communicationService;
_syncInfoPullService = syncInfoPullService;
}
///
/// Gibt eine Entität anhand der eindeutigen Id zurück
///
/// Id der Entität
/// Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten
/// Entität oder null, wenn nicht gefunden
public override DogRace Get(object id, bool noTracking = true)
{
return Repository.SingleOrDefault(c => c.Id == id.ToString(), noTracking);
}
///
/// Gibt eine Entität anhand der eindeutigen Id zurück
///
/// Id der Entität
/// Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten
/// Entität oder null, wenn nicht gefunden
public override async Task GetAsync(object id, bool noTracking = true)
{
return await Repository.SingleOrDefaultAsync(c => c.Id == id.ToString(), noTracking).ConfigureAwait(false);
}
///
/// Gibt eine Liste der Hunderassen zurück.
/// Entweder von der DB oder vom Server
///
/// Aktuelles Accesstoken
/// Gewünschte Sprache
/// CancellationToken
/// Liste der Hunderassen
public async Task> GetRacesAsync(string language, string accessToken, CancellationToken token)
{
//Zuerst DB
var localRaces = await Repository.FindAsync(c => c.Deleted == false, noTracking: true).ConfigureAwait(false);
if (localRaces != null && localRaces.Any())
return localRaces.Where(c => c.Deleted == false).OrderBy(c => c.Name).ToList();
else
{
//Dann wenn lokal nicht verfügbar immer online...
var isConnected = await _communicationService.IsConnected();
//isConnected = false;
if (isConnected)
{
var racesResult = await _communicationService.GetDogRacesAsync(null, language, accessToken, token);
if (racesResult.Success)
{
var result = await HandleChangesAsync(racesResult.Value);
if (result.LastUpdate != null)
await _syncInfoPullService.AddOrUpddateAsync(nameof(DogRace), result.LastUpdate.Value).ConfigureAwait(false);
return racesResult.Value.Where(c => c.Deleted == false).OrderBy(c => c.Name).ToList();
}
}
}
//Keine Daten online, keine offline
return new List();
}
///
/// Gibt eine Hunderasse zurück.
/// Entweder von der DB oder vom Server
///
/// Id der Hunderasse
/// Gewünschte Sprache
/// Aktuelles Accesstoken
/// CancellationToken
/// Hunderasse oder null, wenn nicht gefunden
public async Task GetRaceAsync(string id, string language, string accessToken, CancellationToken token)
{
var localRace = await Repository.FirstOrDefaultAsync(c => c.Deleted == false && c.Id == id, noTracking: true).ConfigureAwait(false);
if (localRace == null)
{
//Dann wenn lokal nicht verfügbar immer online...
var isConnected = await _communicationService.IsConnected();
//isConnected = false;
if (isConnected)
{
var racesResult = await _communicationService.GetDogRaceAsync(id, language, accessToken, token);
if (racesResult.Success)
{
return racesResult.Value;
}
}
}
return localRace;
}
#region Pull-Push Implementation
///
/// Holen der Daten vom lokalen Speicher die noch nicht synchronisiert wurden und senden an den Server
///
/// Aktuelles Accesstoken
/// CancellationToken
/// Task
public async Task> PushAsync(string accessToken, CancellationToken token)
{
var result = new SyncResult();
//Es gibt hier kein Push!
await Task.Delay(1);
return result;
}
///
/// Holen der letzten Daten vom Server und Synchronisieren mit den lokalen Daten
///
/// Sprache
/// Aktuelles Accesstoken
/// CancellationToken
/// Task
public async Task> PullAsync(string language, string accessToken, CancellationToken token)
{
var result = new SyncResult();
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
//Zuerst lezte Aktivität holen...
DateTimeOffset? lastUpdate = null;
var lastSyncInfo = await _syncInfoPullService.GetAsync(nameof(DogRace));
if (lastSyncInfo != null)
lastUpdate = lastSyncInfo.LastUpdate;
var ctsQuery = new CancellationTokenSource(Common.Constants.PushPullTimeout);
var racesResult = await _communicationService.GetDogRacesAsync(lastUpdate, language, accessToken, token);
if (racesResult.Success)
{
result = await HandleChangesAsync(racesResult.Value);
if (result.LastUpdate != null)
await _syncInfoPullService.AddOrUpddateAsync(nameof(DogRace), result.LastUpdate.Value).ConfigureAwait(false);
}
result.LastUpdate ??= lastUpdate;
}
return result;
}
#endregion
#region Private
///
/// Behandeln der Liste von Hunderassen wenn welche vom Online-Store geholt werden.
///
/// Liste der Hunderassen
/// Task
private async Task> HandleChangesAsync(List races)
{
var result = new SyncResult();
//Je Rasse durchgehen ob was gemacht werden soll
foreach (var race in races)
{
var localRace = await Repository.FirstOrDefaultAsync(c => c.Id == race.Id, false);
if (localRace != null && localRace.UpdatedAt < race.UpdatedAt)
{
if (localRace.UpdatedAt >= race.UpdatedAt)
{
if (result.LastUpdate == null || result.LastUpdate < localRace.UpdatedAt)
result.LastUpdate = localRace.UpdatedAt;
continue;
}
var deleted = localRace.Deleted == false && race.Deleted;
localRace.Version = race.Version;
localRace.UpdatedAt = race.UpdatedAt;
localRace.Deleted = race.Deleted;
localRace.Name = race.Name;
localRace.Description = race.Description;
localRace.Age = race.Age;
localRace.SizeAndWeight = race.SizeAndWeight;
localRace.Personality = race.Personality;
localRace.Coexistence = race.Coexistence;
localRace.Care = race.Care;
localRace.Decision = race.Decision;
localRace.Photo = race.Photo;
localRace.Created = race.Created;
if (result.LastUpdate == null || result.LastUpdate < localRace.UpdatedAt)
result.LastUpdate = localRace.UpdatedAt;
if (!deleted)
result.Updated.Add(localRace);
else
result.Deleted.Add(localRace);
Repository.Update(localRace);
}
if (localRace == null)
{
localRace = new DogRace()
{
Id = race.Id,
Version = race.Version,
UpdatedAt = race.UpdatedAt,
Deleted = race.Deleted,
Name = race.Name,
Description = race.Description,
Age = race.Age,
SizeAndWeight = race.SizeAndWeight,
Personality = race.Personality,
Coexistence = race.Coexistence,
Care = race.Care,
Decision = race.Decision,
Photo = race.Photo,
Created = race.Created
};
Repository.Add(localRace);
if (result.LastUpdate == null || result.LastUpdate < localRace.UpdatedAt)
result.LastUpdate = localRace.UpdatedAt;
result.Added.Add(localRace);
}
}
if (result.HasChanges)
{
try
{
await CommitAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
var err = ex.Message;
}
}
return result;
}
#endregion
}
}