using AyCode.Core.Extensions; using AyCode.Core.Interfaces; using AyCode.Core.Serializers; using JsonIgnoreAttribute = Newtonsoft.Json.JsonIgnoreAttribute; using STJIgnore = System.Text.Json.Serialization.JsonIgnoreAttribute; namespace AyCode.Services.SignalRs; /// /// Message container for serialized parameter IDs. /// Optimized for common primitive types to avoid full JSON overhead. /// [Obsolete("Use direct object[] binary serialization instead of IdMessage JSON wrapper.")] public class IdMessage { public List Ids { get; private set; } public IdMessage() { Ids = []; } /// /// Creates IdMessage with multiple parameters serialized directly as JSON. /// public IdMessage(object[] ids) { Ids = new List(ids.Length); for (var i = 0; i < ids.Length; i++) { Ids.Add(SignalRSerializationHelper.SerializePrimitiveToJson(ids[i])); } } /// /// Creates IdMessage with a single parameter serialized as JSON. /// public IdMessage(object id) { Ids = [SignalRSerializationHelper.SerializePrimitiveToJson(id)]; } /// /// Creates IdMessage with multiple Guid parameters. /// public IdMessage(IEnumerable ids) { var idsArray = ids as Guid[] ?? ids.ToArray(); Ids = new List(idsArray.Length); for (var i = 0; i < idsArray.Length; i++) { Ids.Add(SignalRSerializationHelper.SerializeGuidToJson(idsArray[i])); } } public override string ToString() => string.Join("; ", Ids); } /// /// Message containing JSON-serialized post data. /// [Obsolete("Use direct object[] binary serialization instead of JSON-in-Binary wrapper.")] public class SignalPostJsonMessage { public string PostDataJson { get; set; } = ""; public SignalPostJsonMessage() { } protected SignalPostJsonMessage(string postDataJson) => PostDataJson = postDataJson; } /// /// Generic message containing JSON-serialized post data with typed access. /// [Obsolete("Use direct object[] binary serialization instead of JSON-in-Binary wrapper.")] public class SignalPostJsonDataMessage : SignalPostJsonMessage, ISignalPostMessage { [JsonIgnore] [STJIgnore] private TPostDataType? _postData; [JsonIgnore] [STJIgnore] public TPostDataType PostData { get => _postData ??= PostDataJson.JsonTo()!; private init { _postData = value; PostDataJson = _postData.ToJson(); } } public SignalPostJsonDataMessage() : base() { } public SignalPostJsonDataMessage(TPostDataType postData) => PostData = postData; public SignalPostJsonDataMessage(string postDataJson) : base(postDataJson) { } } /// /// Simple message containing post data. /// [Obsolete("Use direct object[] binary serialization instead of message wrappers.")] public class SignalPostMessage(TPostData postData) : ISignalPostMessage { public TPostData? PostData { get; set; } = postData; } [Obsolete("Use direct object[] binary serialization instead of message wrappers.")] public interface ISignalPostMessage : ISignalRMessage { TPostData? PostData { get; } } /// /// Message for requesting by Guid ID. /// public class SignalRequestByIdMessage(Guid id) : ISignalRequestMessage, IId { public Guid Id { get; set; } = id; } public interface ISignalRequestMessage : ISignalRMessage { TRequestId Id { get; set; } } public interface ISignalRMessage { } public interface ISignalResponseMessage : ISignalRMessage { int MessageTag { get; set; } SignalResponseStatus Status { get; set; } } public enum SignalResponseStatus : byte { Error = 0, Success = 5 } /// /// Unified signal response message that supports both JSON and Binary serialization. /// JSON mode uses GZip compression for reduced payload size. /// Optimized: uses pooled buffers for decompression, zero-copy deserialization path. /// /// /// Lightweight response container for client request-response pipeline and stream wire format. /// Main send path does NOT use this — server sends (signalParams + object) directly. /// Used by: (1) client OnReceiveMessage → stores in requestModel, (2) stream path (serialized as blob). /// public sealed class SignalResponseDataMessage : ISignalResponseMessage { public int MessageTag { get; set; } public SignalResponseStatus Status { get; set; } public AcSerializerType DataSerializerType { get; set; } /// /// Raw response object — on client: protocol-deserialized typed object or byte[]. /// On server (stream path only): raw object for blob serialization. /// [JsonIgnore] [STJIgnore] public object? RawResponseData { get; set; } public SignalResponseDataMessage() { } public SignalResponseDataMessage(int messageTag, SignalResponseStatus status) { MessageTag = messageTag; Status = status; } /// Stream path constructor: stores raw object for blob serialization. public SignalResponseDataMessage(int messageTag, SignalResponseStatus status, object? responseData, AcSerializerOptions serializerOptions) : this(messageTag, status) { DataSerializerType = serializerOptions.SerializerType; RawResponseData = responseData; } /// /// Extracts response data as T. /// Protocol eagerly deserializes via SignalDataType → RawResponseData is typed object → direct cast. /// Consumer's responsibility to handle byte[] if T is byte[]. /// public T? GetResponseData() { if (RawResponseData is T typed) return typed; return default; } } public interface IAcSignalRHubClient : IAcSignalRHubBase { Task SendMessageToServerAsync(int messageTag, object[]? parameters, int? requestId); }