import 'dart:typed_data';

class PcmSound {
  final Uint8List bytes;
  PcmSound(this.bytes);
}

class ImfInstruction {
  final int register;
  final int data;
  final int delay; // Delay in 1/700ths of a second

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

class ImfMusic {
  final List<ImfInstruction> instructions;

  ImfMusic(this.instructions);

  factory ImfMusic.fromBytes(Uint8List bytes) {
    List<ImfInstruction> instructions = [];

    // Wolfenstein 3D IMF chunks start with a 16-bit length header (little-endian)
    int actualSize = bytes[0] | (bytes[1] << 8);

    // Start parsing at index 2 to skip the size header
    int limit = 2 + actualSize;
    if (limit > bytes.length) limit = bytes.length; // Safety bounds

    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);
  }
}

typedef WolfMusicMap = List<int>;

/// Maps to the original sound indices from the Wolfenstein 3D source code.
/// Use these to index into `activeGame.sounds[id]`.
abstract class WolfSound {
  // --- Doors & Environment ---
  static const int openDoor = 18;
  static const int closeDoor = 19;
  static const int pushWall = 46; // Secret sliding walls

  // --- Weapons & Combat ---
  static const int knifeAttack = 23;
  static const int pistolFire = 24;
  static const int machineGunFire = 26;
  static const int gatlingFire = 32; // Historically SHOOTSND in the source
  static const int naziFire = 58; // Enemy gunshots

  // --- Pickups & Items ---
  static const int getMachineGun = 30;
  static const int getAmmo = 31;
  static const int getGatling = 38;
  static const int healthSmall = 33; // Dog food / Meals
  static const int healthLarge = 34; // First Aid
  static const int treasure1 = 35; // Cross
  static const int treasure2 = 36; // Chalice
  static const int treasure3 = 37; // Chest
  static const int treasure4 = 45; // Crown
  static const int extraLife = 44; // 1-Up

  // --- Enemies: Standard ---
  static const int guardHalt = 21; // "Halt!"
  static const int dogBark = 41;
  static const int dogDeath = 62;
  static const int dogAttack = 68;
  static const int deathScream1 = 29;
  static const int deathScream2 = 22;
  static const int deathScream3 = 25;
  static const int ssSchutzstaffel = 51; // "Schutzstaffel!"
  static const int ssMeinGott = 63; // SS Death

  // --- Enemies: Bosses (Retail Episodes 1-6) ---
  static const int bossActive = 49;
  static const int mutti = 50; // Hans Grosse Death
  static const int ahhhg = 52;
  static const int eva = 54; // Dr. Schabbs Death
  static const int gutenTag = 55; // Hitler Greeting
  static const int leben = 56;
  static const int scheist = 57; // Hitler Death
  static const int schabbsHas = 64; // Dr. Schabbs
  static const int hitlerHas = 65;
  static const int spion = 66; // Otto Giftmacher
  static const int neinSoVass = 67; // Gretel Grosse Death
  static const int mechSteps = 70; // Mecha-Hitler walking

  // --- UI & Progression ---
  static const int levelDone = 40;
  static const int endBonus1 = 42;
  static const int endBonus2 = 43;
  static const int noBonus = 47;
  static const int percent100 = 48;
}
