namespace NATS.Server.WebSocket;

/// <summary>
/// WebSocket protocol constants (RFC 6455).
/// Ported from golang/nats-server/server/websocket.go lines 41-106.
/// </summary>
public static class WsConstants
{
    // Opcodes (RFC 6455 Section 5.2)
    public const int TextMessage = 1;
    public const int BinaryMessage = 2;
    public const int CloseMessage = 8;
    public const int PingMessage = 9;
    public const int PongMessage = 10;
    public const int ContinuationFrame = 0;

    // Frame header bits
    public const byte FinalBit = 0x80;  // 1 << 7
    public const byte Rsv1Bit = 0x40;   // 1 << 6 (compression, RFC 7692)
    public const byte Rsv2Bit = 0x20;   // 1 << 5
    public const byte Rsv3Bit = 0x10;   // 1 << 4
    public const byte MaskBit = 0x80;   // 1 << 7 (in second byte)

    // Frame size limits
    public const int MaxFrameHeaderSize = 14;
    public const int MaxControlPayloadSize = 125;
    public const int FrameSizeForBrowsers = 4096;
    public const int CompressThreshold = 64;
    public const int CloseStatusSize = 2;

    // Close status codes (RFC 6455 Section 11.7)
    public const int CloseStatusNormalClosure = 1000;
    public const int CloseStatusGoingAway = 1001;
    public const int CloseStatusProtocolError = 1002;
    public const int CloseStatusUnsupportedData = 1003;
    public const int CloseStatusNoStatusReceived = 1005;
    public const int CloseStatusInvalidPayloadData = 1007;
    public const int CloseStatusPolicyViolation = 1008;
    public const int CloseStatusMessageTooBig = 1009;
    public const int CloseStatusInternalSrvError = 1011;
    public const int CloseStatusTlsHandshake = 1015;

    // Compression constants (RFC 7692)
    public const string PmcExtension = "permessage-deflate";
    public const string PmcSrvNoCtx = "server_no_context_takeover";
    public const string PmcCliNoCtx = "client_no_context_takeover";
    public static readonly string PmcReqHeaderValue = $"{PmcExtension}; {PmcSrvNoCtx}; {PmcCliNoCtx}";
    public static readonly string PmcFullResponse = $"Sec-WebSocket-Extensions: {PmcExtension}; {PmcSrvNoCtx}; {PmcCliNoCtx}\r\n";

    // Header names
    public const string NoMaskingHeader = "Nats-No-Masking";
    public const string NoMaskingValue = "true";
    public static readonly string NoMaskingFullResponse = $"{NoMaskingHeader}: {NoMaskingValue}\r\n";
    public const string XForwardedForHeader = "X-Forwarded-For";

    // Path routing
    public const string ClientPath = "/";
    public const string LeafNodePath = "/leafnode";
    public const string MqttPath = "/mqtt";

    // Decompression trailer appended before decompressing (RFC 7692 Section 7.2.2)
    public static readonly byte[] DecompressTrailer = [0x00, 0x00, 0xff, 0xff];

    public static bool IsControlFrame(int opcode) => opcode >= CloseMessage;
}

public enum WsClientKind
{
    Client,
    Leaf,
    Mqtt,
}
