using System.Collections.Concurrent; using System.Diagnostics; using Universal; namespace EEMSClientCore; public class ClientProvider(IClientCaller clientCaller, IClientBaseProvider baseProvider) : IClientProvider { private static readonly ConcurrentDictionary _streamBuffer = []; public static readonly ConcurrentDictionary _savePath = []; //Receive Files from Server public Task PushFile(Guid guid, FileType fileType, byte[] buffer, int current, int total) { if (baseProvider is null) return Task.FromResult(false); if (!_streamBuffer.TryGetValue(fileType, out MemoryStream? stream) || stream is null) { if (current != 1) return Task.FromResult(false); if (!baseProvider.AllowReceiveFile()) return Task.FromResult(false); baseProvider.StartFileReceiveNotify(fileType); stream = new(); _streamBuffer[fileType] = stream; Timer timer = new(FileCleanerTimerCallback, fileType, 600000, Timeout.Infinite); } stream.Write(buffer); if (current != total) return Task.FromResult(true); string? tempPath = fileType switch { FileType.Recipe => baseProvider.RecipePath, FileType.Config => baseProvider.ConfigPath, _ => "Undefined" }; tempPath ??= "Undefined"; string path = Path.Combine(tempPath, "Receive"); if (!Compressor.DecompressZipFile(new(path), stream)) return Task.FromResult(false); if (_streamBuffer.TryRemove(fileType, out MemoryStream? memoryStream) && memoryStream is not null) memoryStream.Dispose(); baseProvider?.FileReceivedNotify(fileType, path); return Task.FromResult(true); } public Task RequestFile(Guid guid, FileType fileType) { Debug.WriteLine($"RequestFile {guid} {fileType}"); string? filePath = fileType switch { FileType.Config => baseProvider.ConfigPath, FileType.Recipe => baseProvider.RecipePath, _ => default }; if (string.IsNullOrEmpty(filePath)) return Task.FromResult(false); if (!Directory.Exists(filePath)) return Task.FromResult(false); using MemoryStream stream = new(); Compressor.CompressZipFileDirectory(new(filePath), stream); return SendFile(guid, stream); } private async Task SendFile(Guid guid, MemoryStream stream) { if (!stream.Split(out List? buffer, 8192) || buffer is null) return false; for (int i = 0; i < buffer.Count; i++) { try { if (!await clientCaller.FilePack(guid, buffer[i], i + 1, buffer.Count)) return false; } catch { return false; } } return true; } private void FileCleanerTimerCallback(object? state) { if (state is not FileType fileType) return; if (_streamBuffer.TryRemove(fileType, out MemoryStream? memoryStream) && memoryStream is not null) memoryStream.Dispose(); } } public interface IClientBaseProvider { string? RecipePath { get; set; } string? ConfigPath { get; set; } bool AllowReceiveFile(); void FileReceivedNotify(FileType fileType, string path); void StartFileReceiveNotify(FileType fileType); }