using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using RMuseum.DbContext;
using RMuseum.Models.Ganjoor;
using RMuseum.Models.Ganjoor.ViewModels;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Models.Image;
using RSecurityBackend.Services;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace RMuseum.Services.Implementation
{
///
/// ganjoor.net banners service
///
public class SiteBannersService : ISiteBannersService
{
///
/// Add site banner
///
///
///
///
///
///
///
public async Task> AddSiteBanner(Stream imageStream, string fileName, string alternateText, string targetUrl, bool active)
{
RServiceResult image = await _imageFileService.Add(null, imageStream, fileName, "SiteBanners");
if (!string.IsNullOrEmpty(image.ExceptionString))
{
return new RServiceResult(null, image.ExceptionString);
}
GanjoorSiteBanner banner = new GanjoorSiteBanner()
{
RImage = image.Result,
AlternateText = alternateText,
TargetUrl = targetUrl,
Active = active
};
_context.GanjoorSiteBanners.Add(banner);
await _context.SaveChangesAsync();
await CleanBannersCache();
return new RServiceResult
(
new GanjoorSiteBannerViewModel()
{
Id = banner.Id,
ImageUrl = $"api/rimages/{banner.RImageId}.jpg",
AlternateText = banner.AlternateText,
TargetUrl = banner.TargetUrl,
Active = banner.Active
}
);
}
///
/// modify site banner
///
///
///
///
///
///
public async Task> ModifySiteBanner(int id, string alternateText, string targetUrl, bool active)
{
GanjoorSiteBanner target = await _context.GanjoorSiteBanners.Where(b => b.Id == id).SingleOrDefaultAsync();
if (target == null)
return new RServiceResult(false);//not found
target.AlternateText = alternateText;
target.TargetUrl = targetUrl;
target.Active = active;
_context.GanjoorSiteBanners.Update(target);
await _context.SaveChangesAsync();
await CleanBannersCache();
return new RServiceResult(true);
}
///
/// delete site banner
///
///
///
public async Task> DeleteSiteBanner(int id)
{
GanjoorSiteBanner target = await _context.GanjoorSiteBanners.Where(b => b.Id == id).SingleOrDefaultAsync();
if (target == null)
return new RServiceResult(false);//not found
_context.GanjoorSiteBanners.Remove(target);
await _context.SaveChangesAsync();
await CleanBannersCache();
return new RServiceResult(true);
}
///
/// get site banners
///
///
public async Task> GetSiteBanners()
{
return new RServiceResult(
await _context.GanjoorSiteBanners
.Select(b => new GanjoorSiteBannerViewModel()
{
Id = b.Id,
ImageUrl = $"api/rimages/{b.RImageId}.jpg",
AlternateText = b.AlternateText,
TargetUrl = b.TargetUrl,
Active = b.Active
}).ToArrayAsync()
);
}
private const string _cacheKeyForIdSet = "SiteBannersService::GetARandomActiveSiteBanner::idSet";
private static string GetBannerCacheKey(int bannerId)
{
return $"SiteBannersService::BannerCacheKey::{bannerId}";
}
private async Task CleanBannersCache()
{
int[] idSet = await _context.GanjoorSiteBanners.Select(b => b.Id).ToArrayAsync();
foreach (int id in idSet)
{
var cacheKey = GetBannerCacheKey(id);
if (_memoryCache.TryGetValue(id, out GanjoorSiteBannerViewModel o))
{
_memoryCache.Remove(id);
}
}
if (_memoryCache.TryGetValue(_cacheKeyForIdSet, out idSet))
{
_memoryCache.Remove(_cacheKeyForIdSet);
}
}
///
/// get a random site banner
///
///
public async Task> GetARandomActiveSiteBanner()
{
if (!_memoryCache.TryGetValue(_cacheKeyForIdSet, out int[] idSet))
{
idSet = await _context.GanjoorSiteBanners.Where(b => b.Active == true).Select(b => b.Id).ToArrayAsync();
_memoryCache.Set(_cacheKeyForIdSet, idSet, TimeSpan.FromHours(1));
}
if (idSet.Length == 0)
return new RServiceResult(null);//no active banner
Random rnd = new Random(DateTime.Now.Millisecond);
int id = idSet[rnd.Next(0, idSet.Length)];
var cachKey = GetBannerCacheKey(id);
if (!_memoryCache.TryGetValue(cachKey, out GanjoorSiteBannerViewModel banner))
{
banner =
await _context.GanjoorSiteBanners
.Where(b => b.Id == id)
.Select(b => new GanjoorSiteBannerViewModel()
{
Id = b.Id,
ImageUrl = $"api/rimages/{b.RImageId}.jpg",
AlternateText = b.AlternateText,
TargetUrl = b.TargetUrl,
Active = b.Active
})
.AsNoTracking()
.SingleAsync();
_memoryCache.Set(cachKey, banner, TimeSpan.FromHours(1));
}
return new RServiceResult(banner);
}
///
/// Database Context
///
protected readonly RMuseumDbContext _context;
///
/// Image File Service
///
protected readonly IImageFileService _imageFileService;
///
/// IMemoryCache
///
protected readonly IMemoryCache _memoryCache;
///
/// constructor
///
///
///
///
public SiteBannersService(RMuseumDbContext context, IImageFileService imageFileService, IMemoryCache memoryCache)
{
_context = context;
_imageFileService = imageFileService;
_memoryCache = memoryCache;
}
}
}