using Microsoft.VisualBasic.CompilerServices;
using Newtonsoft.Json;
using RhythmBase.Converters;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace RhythmBase.Components
{
///
/// Represents a room that can be applied to multiple rooms.
///
[JsonConverter(typeof(RoomConverter))]
public struct RDRoom : IEqualityOperators, IEquatable
{
///
/// Indicates if the top room can be applied.
///
public bool EnableTop { get; }
///
/// Gets or sets whether the specified room is enabled.
///
/// The index of the room.
/// True if the room is enabled; otherwise, false.
[IndexerName("Room")]
public bool this[byte Index]
{
readonly get => _data.HasFlag((RDRoomIndex)(1 << Index));
set
{
if (!(Index >= 4 && !EnableTop))
_data = value ? (_data | (RDRoomIndex)(1 << (int)Index)) : (_data & (RDRoomIndex)(1 << (int)Index));
}
}
///
/// Gets the list of enabled rooms.
///
public readonly List Rooms
{
get
{
RDRoomIndex indexes = _data;
return Enumerable
.Range(0, 5)
.Where(x => indexes.HasFlag((RDRoomIndex)(1 << x)))
.Select(x => (byte)x)
.ToList();
}
}
///
public override readonly string ToString() => string.Format("[{0}]", string.Join(",", Rooms));
///
/// Returns an instance with only room 1 enabled.
///
/// An instance with only room 1 enabled.
public static RDRoom Default() => new(false, [])
{
_data = RDRoomIndex.Room1
};
///
/// Initializes a new instance of the struct.
///
/// Indicates if the top room can be applied.
public RDRoom(bool enableTop) => EnableTop = enableTop;
///
/// Initializes a new instance of the struct with specified rooms.
///
/// Indicates if the top room can be applied.
/// The rooms to be enabled.
public RDRoom(bool enableTop, params byte[] rooms)
{
this = default;
EnableTop = enableTop;
int num = rooms.Length;
if (num != 0)
if (num != 1)
foreach (byte item in rooms)
this[item] = true;
else
this[rooms.Single()] = true;
else
_data = RDRoomIndex.RoomNotAvaliable;
}
///
/// Checks if the specified rooms are included.
///
/// The rooms to check.
/// True if the rooms are included; otherwise, false.
public readonly bool Contains(RDRoom rooms)
{
if (_data == RDRoomIndex.RoomNotAvaliable)
return false;
else
{
for (int i = 0; i < 5; i++)
{
if (this[(byte)i] != rooms[(byte)i])
break;
if (i > 4)
return true;
}
return false;
}
}
///
/// Checks if the specified room is included.
///
/// The room to check.
/// True if the room is included; otherwise, false.
public readonly bool Contains(RDRoomIndex room)
{
return _data.HasFlag(room);
}
///
public static bool operator ==(RDRoom R1, RDRoom R2) => R1._data == R2._data;
///
public static bool operator !=(RDRoom R1, RDRoom R2) => !(R1 == R2);
///
/// Implicitly converts a SingleRoom to a Room.
///
/// The SingleRoom instance to convert.
/// A Room instance.
public static implicit operator RDRoom(RDSingleRoom room) => new(room.EnableTop, [0, ((byte)room.Room)]);
///
/// Explicitly converts a Room to a SingleRoom.
///
/// The Room instance to convert.
/// A SingleRoom instance.
/// Thrown when the Room contains more than one room.
public static explicit operator RDSingleRoom(RDRoom room) =>
room.Rooms.Count == 1
? new RDSingleRoom(room.Rooms.Single())
: throw new Exceptions.RhythmBaseException();
///
public override readonly bool Equals(object? obj) => obj is RDRoom e && Equals(e);
///
public override readonly int GetHashCode() => HashCode.Combine(_data);
///
public readonly bool Equals(RDRoom other) => this == other;
private RDRoomIndex _data;
}
}