import 'dart:typed_data';

/// Represents a raw 8-bit PCM digitized sound effect.
class PcmSound {
  final Uint8List bytes;
  PcmSound(this.bytes);
}

/// A single instruction for the OPL2 (AdLib) FM synthesis chip.
class ImfInstruction {
  /// The OPL2 register to write to.
  final int register;

  /// The data value to write to the register.
  final int data;

  /// The wait time (delay) before the next instruction, measured in 1/700ths of a second.
  final int delay;

  ImfInstruction({
    required this.register,
    required this.data,
    required this.delay,
  });
}

/// Represents a music track in the iD Music Format (IMF).
class ImfMusic {
  final List<ImfInstruction> instructions;

  ImfMusic(this.instructions);

  /// Decodes IMF data from a raw byte buffer.
  ///
  /// IMF files in Wolfenstein 3D are prefixed with a 2-byte little-endian
  /// length header followed by 4-byte instruction chunks.
  factory ImfMusic.fromBytes(Uint8List bytes) {
    List<ImfInstruction> instructions = [];

    // The first 2 bytes are the length of the data portion (excluding header).
    int actualSize = bytes[0] | (bytes[1] << 8);

    // Calculate limit and ensure we don't overflow the source buffer.
    int limit = 2 + actualSize;
    if (limit > bytes.length) limit = bytes.length;

    // Instructions are 4 bytes each: [Reg] [Data] [Delay Low] [Delay High]
    for (int i = 2; i < limit - 3; i += 4) {
      instructions.add(
        ImfInstruction(
          register: bytes[i],
          data: bytes[i + 1],
          delay: bytes[i + 2] | (bytes[i + 3] << 8),
        ),
      );
    }
    return ImfMusic(instructions);
  }
}
