using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using gehGassi.Common.Data;
using gehGassi.Core.Interfaces;
using gehGassi.Domain.Advertisements;
using gehGassi.Domain.Common;
using gehGassi.Domain.News;
using Microsoft.EntityFrameworkCore;
using NetTopologySuite;
using NetTopologySuite.Geometries;
namespace gehGassi.Core.Services
{
///
/// Service der die Verwaltung von News realisiert
///
public class NewsService : ServiceBase, INewsService
{
private readonly IRepository _namesRepository;
///
/// Erstellt eine Instanz
///
/// Instanz eines IUnitOfWork
public NewsService(IUnitOfWork unitOfWork) : base(unitOfWork)
{
_namesRepository = unitOfWork.GetRepository();
}
///
/// Gibt eine gefilterte Liste von News zurück
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// List betroffener News
public IQueryable Filter(string filter)
{
return Repository.Query(c => c.Headline.Contains(filter));
}
///
/// Erstellen einer News
///
/// News
public News Create()
{
var item = new News()
{
Status = NewsStatus.Draft,
Visibility = NewsVisibility.None,
GeoMode = GeoMode.None,
Created = DateTimeOffset.UtcNow,
Location = new Point(0,0){SRID = 4326}
};
return item;
}
///
/// Gibt eine gefilterte Liste von News zurück. Sucht nur im Titel
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// List betroffener News
public async Task> SearchAsync(string filter)
{
return (await Repository.FindAsync(c => c.Headline.Contains(filter))).ToList();
}
///
/// Gibt eine gefilterte Liste von News mit Namen zurück in einer gewählten Sprache
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// Gewünschte Sprache
/// Fallback Sprache
/// Sollen gelöschte inkludiert werden?
/// Liste betroffener News
public IQueryable FilterWithNames(string filter, string language, string fallback, bool includeDeleted)
{
language = language.ToUpperInvariant();
fallback = fallback.ToUpperInvariant();
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Headline.Contains(filter), language, fallback);
if (!includeDeleted)
baseQuery = baseQuery.Where(c => c.Deleted == false);
return baseQuery;
}
///
/// Gibt eine gefilterte Liste von News mit Namen zurück in einer gewählten Sprache
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// Liste nach Bundesländern nach Filter
/// Gewünschte Sprache
/// Fallback Sprache
/// Sollen gelöschte inkludiert werden?
/// Liste von Ländern nach Filter
/// Liste betroffener News
public IQueryable FilterWithNames(string filter, List countries, List states, string language, string fallback, bool includeDeleted)
{
language = language.ToUpperInvariant();
fallback = fallback.ToUpperInvariant();
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Headline.Contains(filter), language, fallback);
if (countries.Any())
baseQuery = baseQuery.Where(c => c.CountryCode != null && c.CountryCode != "" && countries.Contains(c.CountryCode));
if (states.Any())
baseQuery = baseQuery.Where(c => c.State != null && c.State != "" && states.Contains(c.State));
if (!includeDeleted)
baseQuery = baseQuery.Where(c => c.Deleted == false);
return baseQuery;
}
///
/// Gibt eine Liste von News-Meldungen für die App zurück. Es werden nur laufende News berücksichtigt
///
/// Sichtbar für wen? Wird adaptiert!
/// Gewünschte Kategorie oder leer wenn alle
/// Land
/// Bundesland
/// Optional: Breitengrad
/// Optional: Längengrad
/// Gewünschte Sprache
/// Fallback Sprache
/// Datensätze auslassen
/// Datensätze nehmen
/// Liste passender News
public async Task<(int total, List list)> GetForAppAsync(NewsVisibility visibility, string categoryId, string country, string state, double? lat, double? lng, string language, string fallback, int skip, int take)
{
language = language.ToUpperInvariant();
fallback = fallback.ToUpperInvariant();
if(!string.IsNullOrWhiteSpace(country))
country = country.ToUpperInvariant();
if (!string.IsNullOrWhiteSpace(state))
state = state.ToUpperInvariant();
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var location = geometryFactory.CreatePoint(new Coordinate(lng.Value, lat.Value));
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.CategoryId == categoryId && c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners) &&
(c.GeoMode == GeoMode.None ||
(c.GeoMode == GeoMode.Country && c.CountryCode == country) ||
(c.GeoMode == GeoMode.CountryAndState && c.CountryCode == country && c.State == state) ||
(c.GeoMode == GeoMode.Location && c.Location.IsWithinDistance(location, c.Radius * 1000))), language, fallback);
//if (geoMode == GeoMode.None)
//{
// var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.None && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback);
// if(!string.IsNullOrEmpty(categoryId))
// baseQuery = baseQuery.Where(c => c.CategoryId == categoryId);
// return await baseQuery.ToListAsync().ConfigureAwait(false);
//}
//else if (geoMode == GeoMode.Country && !string.IsNullOrWhiteSpace(country))
//{
// var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Country && c.CountryCode == country && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback);
// if (!string.IsNullOrEmpty(categoryId))
// baseQuery = baseQuery.Where(c => c.CategoryId == categoryId);
// return await baseQuery.ToListAsync().ConfigureAwait(false);
//}
//else if (geoMode == GeoMode.CountryAndState && !string.IsNullOrWhiteSpace(country) && !string.IsNullOrWhiteSpace(state))
//{
// var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.CountryAndState && c.CountryCode == country && c.State == state && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback);
// if (!string.IsNullOrEmpty(categoryId))
// baseQuery = baseQuery.Where(c => c.CategoryId == categoryId);
// return await baseQuery.ToListAsync().ConfigureAwait(false);
//}
//else if(geoMode == GeoMode.Location && lat.HasValue && lng.HasValue)
//{
// //Lokalisierungsmodus --> Andere Abfrage weil wir die Distanz zu den Geokoordinaten brauchen
// var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
// var location = geometryFactory.CreatePoint(new Coordinate(lng.Value, lat.Value));
// var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Location && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback);
// baseQuery = baseQuery.Where(c => c.Location.IsWithinDistance(location, c.Radius * 1000));
// if (!string.IsNullOrEmpty(categoryId))
// baseQuery = baseQuery.Where(c => c.CategoryId == categoryId);
// return await baseQuery.ToListAsync().ConfigureAwait(false);
// //var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNamesDistance({0},{1},{2},{3})", c => c.Deleted == false && c.Status == NewsStatus.Running && c.Language == language && c.GeoMode == GeoMode.Location && (c.Visibility == visibility || c.Visibility == NewsVisibility.DogWalkerAndOwners), language, fallback, lat.Value, lng.Value);
// //if (!string.IsNullOrEmpty(categoryId))
// // baseQuery = baseQuery.Where(c => c.CategoryId == categoryId);
// //return await baseQuery.ToListAsync().ConfigureAwait(false);
//}
var total = await baseQuery.CountAsync().ConfigureAwait(false);
var list = await baseQuery.OrderByDescending(c => c.Start).ThenBy(c => c.Location.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false);
return (total, list);
}
///
/// Gibt eine News mit Sprachen aufgelöst zurück
///
/// Id der News
/// Gewünschte Sprache
/// Fallback Sprache
/// News mit Namen aufgelöst
public async Task GetWithNamesAsync(long newsId, string language, string fallback)
{
language = language.ToUpperInvariant();
fallback = fallback.ToUpperInvariant();
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_NewsWithNames({0},{1})", c => c.Deleted == false && c.Id == newsId, language, fallback);
return await baseQuery.FirstOrDefaultAsync().ConfigureAwait(false);
}
///
/// Starten von freigegebenen News wenn diese das Start-Datum erreicht haben
///
/// Anzahl gestartete News
public async Task StartApprovedAsnyc()
{
var items = await Repository.FindAsync(c => c.Status == NewsStatus.Approved && c.Deleted == false && c.Start <= DateTimeOffset.UtcNow && c.End.Value >= DateTimeOffset.UtcNow);
foreach (var item in items)
{
item.Status = NewsStatus.Running;
}
return items.Count();
}
///
/// Stoppen von abgelaufenen News wenn diese das Enddatum erreicht haben
///
/// Anzahl gestoppte News
public async Task StopRunningAsync()
{
var items = await Repository.FindAsync(c => c.Status == NewsStatus.Running && c.Deleted == false && c.End.Value <= DateTimeOffset.UtcNow);
foreach (var item in items)
{
item.Status = NewsStatus.Ended;
}
return items.Count();
}
}
}