using AutoMapper;
using gehGassi.Core.Interfaces;
using gehGassi.Core.Services;
using gehGassi.Dto.News;
using gehGassi.Dto;
using gehGassi.Web.Helper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using gehGassi.Dto.Dogs;
using gehGassi.Dto.Common;
using gehGassi.Dto.Messages;
using NuGet.Protocol.Plugins;
using Microsoft.AspNetCore.Http;
using System.IO;
using gehGassi.Domain.Dogs;
using gehGassi.Web.Auth;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Processing;
using gehGassi.Web.Models;
using Asp.Versioning;
namespace gehGassi.Web.Controllers.Api
{
///
/// Controller der Zugriff auf Hunde und Hunderassen via API ermöglicht
///
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[ApiVersion(1)]
[Route("api/dogs")]
[Route("api/v{v:apiVersion}/dogs")]
public class ApiDogsController : ApiBaseController
{
private readonly ILogger _logger;
private readonly IDogRaceService _dogRaceService;
private readonly IDogService _dogService;
///
/// Erstellt eine Instanz
///
/// Instanz eines IMapper
/// Instanz eines ILogger
/// Instanz von LocalizationOptions
/// Instanz eines IAppUserService
/// Instanz eines IDogRaceService
/// Instanz eines IDogService
public ApiDogsController(IMapper mapper, ILogger logger, IOptions localizationOptions, IAppUserService appUserService, IDogRaceService dogRaceService,
IDogService dogService) : base(mapper, localizationOptions, appUserService)
{
_logger = logger;
_dogRaceService = dogRaceService;
_dogService = dogService;
}
///
/// Gibt eine Liste von Hunderassen für die Synchronisierung mit der App zurück
///
/// Letztes Update oder null, wenn noch keines
/// Gewünschte Sprache
/// HTTP 200 wenn erfolgreich
[Route("GetRaces")]
[HttpGet]
public async Task GetRaces(DateTimeOffset? lastUpdate, string language)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var races = await _dogRaceService.GetForSyncAsync(lastUpdate, language, LocalizationOptions.Value.DefaultCulture);
var racesDto = Mapper.Map>(races);
return Ok(racesDto);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt eine eine Hunderassen zurück
///
/// Id der hunderasse
/// Gewünschte Sprache
/// HTTP 200 wenn erfolgreich
[Route("GetRace")]
[HttpGet]
public async Task GetRace(string id, string language)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var race = await _dogRaceService.GetWithNamesAsync(id, language, LocalizationOptions.Value.DefaultCulture);
var raceDto = Mapper.Map(race);
return Ok(raceDto);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der Hunde eines AppUsers
///
/// Id des AppUsers
/// Letztes Update oder null, wenn noch keines
/// Liste der Hunde
[HttpGet]
[Route("GetDogs")]
public async Task GetDogs(string appUserId, DateTimeOffset? lastUpdate)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var dogs = await _dogService.GetDogsAsync(appUserId, lastUpdate);
var dogsDtoList = Mapper.Map>(dogs);
var baseAddress = GetBaseAddress();
foreach (var item in dogsDtoList)
{
item.Photo = !string.IsNullOrWhiteSpace(item.Photo) ? $"{baseAddress}/file/documents/thumbnails/{400}/{item.Photo}" : "";
}
return Ok(dogsDtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der Hunde eines AppUsers als DogMinInfo
///
/// Id des Hundebesitzers
/// Gewünschte Sprache
/// Liste der Hunde als MinInfo
[HttpGet]
[Route("GetDogsMin")]
public async Task GetDogsMin(string dogOwnerId, string language)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var appUserId = User.AppUserId();
var locked = await AppUserService.IsLockedAsync(dogOwnerId);
var blocked = await AppUserService.IsBlockedAsync(appUserId, dogOwnerId);
var dogs = await _dogService.GetWithNamesOwnerAsync(dogOwnerId, language, LocalizationOptions.Value.DefaultCulture);
var dogsDtoList = Mapper.Map>(dogs);
var baseAddress = GetBaseAddress();
foreach (var item in dogsDtoList)
{
item.Photo = !string.IsNullOrWhiteSpace(item.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{item.Photo}" : "";
item.Locked = locked;
item.Blocked = blocked;
}
return Ok(dogsDtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt einen hund zurück
///
/// Id des Hundes
/// Hunde
[HttpGet]
[Route("GetDog")]
public async Task GetDog(string dogId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var dog = await _dogService.GetAsync(dogId);
var dogDto = Mapper.Map(dog);
var baseAddress = GetBaseAddress();
dogDto.Photo = !string.IsNullOrWhiteSpace(dogDto.Photo) ? $"{baseAddress}/file/documents/thumbnails/{400}/{dogDto.Photo}" : "";
var appUserId = User.AppUserId();
dogDto.Locked = await AppUserService.IsLockedAsync(dog.AppUserId);
dogDto.Blocked = await AppUserService.IsBlockedAsync(appUserId, dog.AppUserId);
return Ok(dogDto);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen eines Hundes
///
/// DogDto
/// Optional Foto
/// CreateResponseDto
[HttpPost]
[Route("Add")]
public async Task Add([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, IFormFile photoUpdateFile)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var dog = await _dogService.GetAsync(model.Id);
if (dog == null)
{
dog = _dogService.Create();
Mapper.Map(model, dog);
dog.Id = model.Id; //Da die Id schon in der App generiert wurde
if (model.BirthDate.HasValue)
dog.BirthDate = new DateTimeOffset(model.BirthDate.Value.DateTime, TimeSpan.Zero);
dog.Number = await _dogService.GetNextNumberAsync();
try
{
if (photoUpdateFile != null && !string.IsNullOrEmpty(photoUpdateFile.FileName))
{
var extension = Path.GetExtension(photoUpdateFile.FileName);
var filenameToUse = FileServiceHelper.GetDogPath(dog.Id) + $"dog_{Guid.NewGuid():N}{extension}";
using var memoryStream = new MemoryStream();
await photoUpdateFile.CopyToAsync(memoryStream);
memoryStream.Position = 0;
using var img = await Image.LoadAsync(memoryStream);
img.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new Size(800) }));
var format = img.DetectEncoder(photoUpdateFile.FileName);
await using var memStream = new MemoryStream();
await img.SaveAsync(memStream, format);
memStream.Position = 0;
await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, memStream);
dog.Photo = filenameToUse;
//Thumbnails erstellten
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100);
}
}
catch (Exception ex)
{
}
_dogService.Add(dog);
await _dogService.CommitAsync(User.Identity.Name);
var dtoDog = Mapper.Map(dog);
result.Status = CreateStatusDto.Success;
result.Value = dtoDog;
return Ok(result);
}
result.Status = CreateStatusDto.Exists;
return Ok(result);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Aktualisieren eines Hundes
///
/// DogDto
/// Optional Foto
/// 200OK
[HttpPost]
[Route("Update")]
public async Task Update([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, IFormFile photoUpdateFile)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var dog = await _dogService.GetAsync(model.Id);
if (dog != null)
{
if (model.UpdatedAt > dog.UpdatedAt)
{
var oldPhoto = dog.Photo;
Mapper.Map(model, dog);
if (string.IsNullOrWhiteSpace(model.Photo) || model.Photo.StartsWithHttp())
{
//Altes Foto behalten wenn eines als Link kommt
dog.Photo = oldPhoto;
}
try
{
if (photoUpdateFile != null && !string.IsNullOrEmpty(photoUpdateFile.FileName))
{
//Wenn es ein altes Foto gibt, dieses löschen
if (!string.IsNullOrWhiteSpace(oldPhoto))
{
await FileService.DeleteAsync(FileServiceHelper.DocumentContainer, oldPhoto);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 400);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 200);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, oldPhoto, 100);
}
var extension = Path.GetExtension(photoUpdateFile.FileName);
var filenameToUse = FileServiceHelper.GetDogPath(dog.Id) + $"dog_{Guid.NewGuid():N}{extension}";
using var memoryStream = new MemoryStream();
await photoUpdateFile.CopyToAsync(memoryStream);
memoryStream.Position = 0;
using var img = await Image.LoadAsync(memoryStream);
img.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Crop, Size = new Size(800) }));
var format = img.DetectEncoder(photoUpdateFile.FileName);
await using var memStream = new MemoryStream();
await img.SaveAsync(memStream, format);
memStream.Position = 0;
await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, memStream);
dog.Photo = filenameToUse;
//Thumbnails erstellten
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200);
await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100);
}
}
catch (Exception ex)
{
}
await _dogService.CommitAsync(User.Identity.Name);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Löschen eines Hundes
///
/// DogDto
/// Id des App-Users
/// 200OK
[HttpPost]
[Route("Delete")]
public async Task Delete([ModelBinder(BinderType = typeof(JsonModelBinder))] DogDto model, [FromQuery]string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var dog = await _dogService.GetAsync(model.Id);
if (dog != null)
{
var appUser = await AppUserService.GetAsync(appUserId);
if (appUser != null)
{
if (dog.AppUserId == appUser.Id)
{
var postingPath = FileServiceHelper.GetDogPath(dog.Id);
await FileService.ClearDirectoryAsync(FileServiceHelper.DocumentContainer, postingPath);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 400);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 200);
await RemoveThumbnail(FileServiceHelper.DocumentContainer, dog.Photo, 100);
_dogService.Remove(dog);
await _dogService.CommitAsync(User.Identity.Name);
return Ok();
}
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
}
}