using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NetVips;
using Image = NetVips.Image;
namespace API.Services;
public interface IImageService
{
    void ExtractImages(string fileFilePath, string targetDirectory, int fileCount = 1);
    string GetCoverImage(string path, string fileName, string outputDirectory, bool saveAsWebP = false);
    /// 
    /// Creates a Thumbnail version of a base64 image
    /// 
    /// base64 encoded image
    /// 
    /// Width of thumbnail
    /// File name with extension of the file. This will always write to 
    string CreateThumbnailFromBase64(string encodedImage, string fileName, int thumbnailWidth = 0);
    string WriteCoverThumbnail(Stream stream, string fileName, string outputDirectory, bool saveAsWebP = false);
    /// 
    /// Converts the passed image to webP and outputs it in the same directory
    /// 
    /// Full path to the image to convert
    /// Where to output the file
    /// File of written webp image
    Task ConvertToWebP(string filePath, string outputPath);
    Task IsImage(string filePath);
}
public class ImageService : IImageService
{
    private readonly ILogger _logger;
    private readonly IDirectoryService _directoryService;
    public const string ChapterCoverImageRegex = @"v\d+_c\d+";
    public const string SeriesCoverImageRegex = @"series\d+";
    public const string CollectionTagCoverImageRegex = @"tag\d+";
    public const string ReadingListCoverImageRegex = @"readinglist\d+";
    /// 
    /// Width of the Thumbnail generation
    /// 
    private const int ThumbnailWidth = 320;
    /// 
    /// Width of a cover for Library
    /// 
    public const int LibraryThumbnailWidth = 32;
    public ImageService(ILogger logger, IDirectoryService directoryService)
    {
        _logger = logger;
        _directoryService = directoryService;
    }
    public void ExtractImages(string fileFilePath, string targetDirectory, int fileCount = 1)
    {
        _directoryService.ExistOrCreate(targetDirectory);
        if (fileCount == 1)
        {
            _directoryService.CopyFileToDirectory(fileFilePath, targetDirectory);
        }
        else
        {
            _directoryService.CopyDirectoryToDirectory(Path.GetDirectoryName(fileFilePath), targetDirectory,
                Tasks.Scanner.Parser.Parser.ImageFileExtensions);
        }
    }
    public string GetCoverImage(string path, string fileName, string outputDirectory, bool saveAsWebP = false)
    {
        if (string.IsNullOrEmpty(path)) return string.Empty;
        try
        {
            using var thumbnail = Image.Thumbnail(path, ThumbnailWidth);
            var filename = fileName + (saveAsWebP ? ".webp" : ".png");
            thumbnail.WriteToFile(_directoryService.FileSystem.Path.Join(outputDirectory, filename));
            return filename;
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "[GetCoverImage] There was an error and prevented thumbnail generation on {ImageFile}. Defaulting to no cover image", path);
        }
        return string.Empty;
    }
    /// 
    /// Creates a thumbnail out of a memory stream and saves to  with the passed
    /// fileName and .png extension.
    /// 
    /// Stream to write to disk. Ensure this is rewinded.
    /// filename to save as without extension
    /// Where to output the file, defaults to covers directory
    /// Export the file as webP otherwise will default to png
    /// File name with extension of the file. This will always write to 
    public string WriteCoverThumbnail(Stream stream, string fileName, string outputDirectory, bool saveAsWebP = false)
    {
        using var thumbnail = Image.ThumbnailStream(stream, ThumbnailWidth);
        var filename = fileName + (saveAsWebP ? ".webp" : ".png");
        _directoryService.ExistOrCreate(outputDirectory);
        try
        {
            _directoryService.FileSystem.File.Delete(_directoryService.FileSystem.Path.Join(outputDirectory, filename));
        } catch (Exception) {/* Swallow exception */}
        thumbnail.WriteToFile(_directoryService.FileSystem.Path.Join(outputDirectory, filename));
        return filename;
    }
    public Task ConvertToWebP(string filePath, string outputPath)
    {
        var file = _directoryService.FileSystem.FileInfo.FromFileName(filePath);
        var fileName = file.Name.Replace(file.Extension, string.Empty);
        var outputFile = Path.Join(outputPath, fileName + ".webp");
        using var sourceImage = Image.NewFromFile(filePath, false, Enums.Access.SequentialUnbuffered);
        sourceImage.WriteToFile(outputFile);
        return Task.FromResult(outputFile);
    }
    public async Task IsImage(string filePath)
    {
        try
        {
            var info = await SixLabors.ImageSharp.Image.IdentifyAsync(filePath);
            if (info == null) return false;
            return true;
        }
        catch (Exception)
        {
            /* Swallow Exception */
        }
        return false;
    }
    /// 
    public string CreateThumbnailFromBase64(string encodedImage, string fileName, int thumbnailWidth = ThumbnailWidth)
    {
        try
        {
            using var thumbnail = Image.ThumbnailBuffer(Convert.FromBase64String(encodedImage), ThumbnailWidth);
            var filename = fileName + ".png";
            thumbnail.WriteToFile(_directoryService.FileSystem.Path.Join(_directoryService.CoverImageDirectory, fileName + ".png"));
            return filename;
        }
        catch (Exception e)
        {
            _logger.LogError(e, "Error creating thumbnail from url");
        }
        return string.Empty;
    }
    /// 
    /// Returns the name format for a chapter cover image
    /// 
    /// 
    /// 
    /// 
    public static string GetChapterFormat(int chapterId, int volumeId)
    {
        return $"v{volumeId}_c{chapterId}";
    }
    /// 
    /// Returns the name format for a library cover image
    /// 
    /// 
    /// 
    public static string GetLibraryFormat(int libraryId)
    {
        return $"l{libraryId}";
    }
    /// 
    /// Returns the name format for a series cover image
    /// 
    /// 
    /// 
    public static string GetSeriesFormat(int seriesId)
    {
        return $"series{seriesId}";
    }
    /// 
    /// Returns the name format for a collection tag cover image
    /// 
    /// 
    /// 
    public static string GetCollectionTagFormat(int tagId)
    {
        return $"tag{tagId}";
    }
    /// 
    /// Returns the name format for a reading list cover image
    /// 
    /// 
    /// 
    public static string GetReadingListFormat(int readingListId)
    {
        return $"readinglist{readingListId}";
    }
}