import 'package:wolf_3d_dart/src/entities/entities/collectible.dart';
import 'package:wolf_3d_dart/src/entities/entities/decorations/dead_aardwolf.dart';
import 'package:wolf_3d_dart/src/entities/entities/decorations/dead_guard.dart';
import 'package:wolf_3d_dart/src/entities/entities/decorative.dart';
import 'package:wolf_3d_dart/src/entities/entities/enemies/bosses/hans_grosse.dart';
import 'package:wolf_3d_dart/src/entities/entities/enemies/enemy.dart';
import 'package:wolf_3d_dart/src/entities/entity.dart';
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';

/// Defines a standard signature for entity spawning functions.
typedef EntitySpawner =
    Entity? Function(
      int objId,
      double x,
      double y,
      Difficulty difficulty, {
      bool isSharewareMode,
    });

/// The central factory for instantiating all dynamic objects in a Wolf3D level.
///
/// This registry uses a prioritized list of spawners. Specialized entities
/// (like bosses or unique decorations) are checked first, followed by
/// generic enemies and finally collectibles.
abstract class EntityRegistry {
  /// Ordered list of spawner functions used to identify Map IDs.
  static final List<EntitySpawner> _spawners = [
    // 1. Special Case Decorations (Legacy items from source)
    DeadGuard.trySpawn,
    DeadAardwolf.trySpawn,

    // 2. Boss Entities
    HansGrosse.trySpawn,

    // 3. Static Decorative Objects (Puddles, Lamps, etc.)
    Decorative.trySpawn,

    // 4. Combat Enemies (Guard, SS, Mutant, Officer, Dog)
    Enemy.spawn,

    // 5. Pickups (Health, Ammo, Keys)
    Collectible.trySpawn,
  ];

  /// Interprets a [objId] from the map and returns the corresponding [Entity].
  ///
  /// Returns `null` if the ID is 0 or is not recognized by any registered spawner.
  static Entity? spawn(
    int objId,
    double x,
    double y,
    Difficulty difficulty,
    int maxSprites, {
    bool isSharewareMode = false,
  }) {
    if (objId == 0) return null;

    for (final spawner in _spawners) {
      Entity? entity = spawner(
        objId,
        x,
        y,
        difficulty,
        isSharewareMode: isSharewareMode,
      );
      if (entity != null) return entity;
    }
    return null;
  }
}
