import { BinaryClassSerializationAdapter } from "../../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
import { NetworkIdentity } from "../components/NetworkIdentity.js";

/**
 * Highest `owner_peer_id` value the wire format can faithfully represent.
 * Above this the +1 bias would alias into the "unowned" sentinel encoding.
 * Documented here so callers can see the limit without spelunking the
 * adapter internals.
 *
 * @type {number}
 */
export const MAX_OWNER_PEER_ID = 0xFFFD;

/**
 * Save-game adapter for {@link NetworkIdentity}.
 *
 * Wire layout: `network_id_varint, owner_peer_id_uint16, replication_flags_uint8`.
 *
 * Note: this is for *save-game* persistence, not the per-tick replication
 * stream. Network packets carry `network_id` inside individual `SimAction`
 * payloads; the component itself doesn't go on the wire (the receiver creates
 * a fresh NetworkIdentity locally).
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */
export class NetworkIdentitySerializationAdapter extends BinaryClassSerializationAdapter {

    klass = NetworkIdentity;
    version = 1;

    /**
     * @param {BinaryBuffer} buffer
     * @param {NetworkIdentity} value
     */
    serialize(buffer, value) {
        // network_id can be -1 (unassigned). Bias by 1 so the varint stays small.
        buffer.writeUintVar(value.network_id + 1);
        // owner_peer_id can also be -1; bias by 1 into uint16 range. Mask
        // would silently alias values >= 0xFFFE into the "unowned" sentinel.
        // We throw instead so the truncation can't slip through in a
        // production bundle (where assertions are stripped). Lift to a
        // wider field on the wire if we ever expect more than ~65k
        // concurrent peers.
        if (value.owner_peer_id > MAX_OWNER_PEER_ID) {
            throw new Error(
                `NetworkIdentitySerializationAdapter: owner_peer_id ${value.owner_peer_id} exceeds the wire format limit (${MAX_OWNER_PEER_ID}); ` +
                `widen the wire format if more peers are needed`
            );
        }
        buffer.writeUint16((value.owner_peer_id + 1) & 0xFFFF);
        buffer.writeUint8(value.replication_flags & 0xFF);
    }

    /**
     * @param {BinaryBuffer} buffer
     * @param {NetworkIdentity} value
     */
    deserialize(buffer, value) {
        value.network_id = buffer.readUintVar() - 1;
        value.owner_peer_id = buffer.readUint16() - 1;
        value.replication_flags = buffer.readUint8();
    }
}
