// Copyright 2020-2025 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Adapted from server/websocket.go in the NATS server Go source.

namespace ZB.MOM.NatsNet.Server.WebSocket;

/// <summary>
/// WebSocket opcode values as defined in RFC 6455 §5.2.
/// Mirrors Go <c>wsOpCode</c> type in server/websocket.go.
/// </summary>
internal enum WsOpCode : int
{
    Continuation = 0,
    Text         = 1,
    Binary       = 2,
    Close        = 8,
    Ping         = 9,
    Pong         = 10,
}

/// <summary>
/// WebSocket protocol constants.
/// Mirrors the constant block at the top of server/websocket.go.
/// </summary>
internal static class WsConstants
{
    public static readonly byte[] CompressLastBlock = [0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff];

    // Frame header bits
    public const int FinalBit              = 1 << 7;
    public const int Rsv1Bit               = 1 << 6; // Used for per-message compression (RFC 7692)
    public const int Rsv2Bit               = 1 << 5;
    public const int Rsv3Bit               = 1 << 4;
    public const int MaskBit               = 1 << 7;

    // Frame size limits
    public const int MaxFrameHeaderSize    = 14; // LeafNode may behave as a client
    public const int MaxControlPayloadSize = 125;
    public const int FrameSizeForBrowsers  = 4096; // From experiment, browsers behave better with limited frame size
    public const int CompressThreshold     = 64;   // Don't compress for small buffer(s)
    public const int CloseStatusSize       = 2;

    // Close status codes (RFC 6455 §11.7)
    public const int CloseNormalClosure       = 1000;
    public const int CloseGoingAway           = 1001;
    public const int CloseProtocolError       = 1002;
    public const int CloseUnsupportedData     = 1003;
    public const int CloseNoStatusReceived    = 1005;
    public const int CloseInvalidPayloadData  = 1007;
    public const int ClosePolicyViolation     = 1008;
    public const int CloseMessageTooBig       = 1009;
    public const int CloseInternalError       = 1011;
    public const int CloseTlsHandshake        = 1015;

    // Header strings
    public const string NoMaskingHeader       = "Nats-No-Masking";
    public const string NoMaskingValue        = "true";
    public const string XForwardedForHeader   = "X-Forwarded-For";
    public const string PMCExtension          = "permessage-deflate"; // per-message compression
    public const string PMCSrvNoCtx           = "server_no_context_takeover";
    public const string PMCCliNoCtx           = "client_no_context_takeover";
    public const string SecProtoHeader        = "Sec-Websocket-Protocol";
    public const string MQTTSecProtoVal       = "mqtt";
    public const string SchemePrefix          = "ws";
    public const string SchemePrefixTls       = "wss";
}
