namespace DorkNet.Server.Services;
///
/// Converts between a sub-room's position in the room
/// (, 0-based, what the
/// server stores and indexes on) and the SubRoomId the 2023 client
/// sees on the wire.
///
/// Why they differ. The client refuses to load a sub-room whose
/// id is not positive: SubroomModel.DOKCPLJOKIE
/// (IsilDump/Assembly-CSharp/RRUI/Data/SubroomModel.txt:3) is
/// RoomId > 0 && SubroomId > 0, and
/// Model`1.LNPEMMMGCPC skips the load when it is false. With the
/// first sub-room advertised as id 0, its Room Settings > Subrooms row
/// never fetched its details (SubroomModel.KBOJBJNCOGK →
/// FGCPNAACHIK.OBFPEGLLELP(long?)), so the row showed no name, and
/// every per-row action (rename, max players, permissions, duplicate) ran
/// against a null sub-room. Rec Room's own ids were large unique numbers;
/// the client needs only "positive and stable per room".
///
/// Mapping. Wire id = OrderIndex + 1, so a room's first
/// sub-room is 1. Incoming ids go back through ;
/// 0 (and anything negative) is accepted as an alias of the first sub-room,
/// which keeps cached client state, old presence rows and bare
/// matchmake/room/{id} joins working.
///
/// Where the conversion happens. Only at the wire: the room
/// details SubRooms[], the sub-room routes
/// (rooms/{id}/subrooms/{sub}/*), matchmake/room/{id}/{sub},
/// the room-instance JSON (RoomInstanceDto.subRoomId), the instance
/// browser, sub-room save DTOs and permission rows. Everything stored
/// (RoomScenes, PrivateInstances, RoomDataBlobs, presence) keeps the
/// OrderIndex.
///
public static class RoomSceneIds
{
/// OrderIndex → wire SubRoomId (always ≥ 1).
public static long ToWire(long orderIndex) => Math.Max(0, orderIndex) + 1;
/// Wire SubRoomId → OrderIndex. 0 and negatives map to the first
/// sub-room.
public static int ToOrderIndex(long wireSubRoomId)
=> wireSubRoomId <= 1 ? 0 : (int)Math.Min(int.MaxValue, wireSubRoomId - 1);
}