// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.JSInterop;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.FormatConverters;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.Service;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.WellKnownTypes;
using System.IO.Compression;

namespace SelmoStudio.Hmi.Server.Shared.Service
{
    internal class FileDownloadService : IFileDownloadService
    {
        private readonly IJSRuntime _jsRuntime;
        private Lazy<IJSObjectReference> _accessorJsRef = new();

        public FileDownloadService(IJSRuntime jsRuntime)
        {
            _jsRuntime = jsRuntime;
        }

        public async Task DownloadAsync(string fileName, WellKnownFileFormat fileFormat, object content)
        {
            await (fileFormat switch
            {
                WellKnownFileFormat.Text => DownloadAsync(fileName, fileFormat.GetSymbol(), content),
                WellKnownFileFormat.Json => DownloadAsync(fileName, fileFormat.GetSymbol(), JsonConversion.Convert(content)),
                WellKnownFileFormat.Pdf => DownloadAsync(fileName, fileFormat.GetSymbol(), await PdfConversion.ConvertAsync(content.ToString())),
                WellKnownFileFormat.Zip => DownloadAsync(fileName, fileFormat.GetSymbol(), (byte[])content),
                _ => throw new NotImplementedException("The download mechanism for the file type has to be implemented.")
            });
        }

        private async Task DownloadAsync(string fileName, string contentType, object content)
        {
            await WaitForReference();
            await _accessorJsRef.Value.InvokeVoidAsync("download", fileName, contentType, content);
        }

        public async Task DownloadAsync<T>(string fileName, WellKnownFileFormat fileFormat, List<T> content)
        {
            await WaitForReference();

            await (fileFormat switch
            {
                WellKnownFileFormat.Csv => _accessorJsRef.Value.InvokeVoidAsync("download", fileName, fileFormat.GetSymbol(), CsvConversion.Convert<T>(content)),
                _ => throw new NotImplementedException("The download mechanism for the file type has to be implemented.")
            });
        }

        private async Task WaitForReference()
        {
            if (_accessorJsRef.IsValueCreated is false)
            {
                _accessorJsRef = new(await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "/js/FileDownloader.js"));
            }
        }
    }
}