import 'package:wolf_3d_dart/src/data_types/game_version.dart';

/// Canonical music identifiers used by built-in registries.
enum Music {
  // --- Menus & UI ---
  menuTheme(retailTrackIndex: 1, sharewareTrackIndex: 1),

  // --- Gameplay ---
  // Generic level-slot keys used when routing by episode+floor index.
  level01(retailTrackIndex: 2, sharewareTrackIndex: 2),
  level02(retailTrackIndex: 3, sharewareTrackIndex: 3),
  level03(retailTrackIndex: 4, sharewareTrackIndex: 4),
  level04(retailTrackIndex: 5, sharewareTrackIndex: 5),
  level05(retailTrackIndex: 6, sharewareTrackIndex: 6),
  level06(retailTrackIndex: 7, sharewareTrackIndex: 7),
  level07(retailTrackIndex: 8),
  level08(retailTrackIndex: 9),
  level09(retailTrackIndex: 10),
  level10(retailTrackIndex: 11),
  level11(retailTrackIndex: 12),
  level12(retailTrackIndex: 13),
  level13(retailTrackIndex: 14),
  level14(retailTrackIndex: 15),
  level15(retailTrackIndex: 16),
  level16(retailTrackIndex: 17),
  level17(retailTrackIndex: 18),
  level18(retailTrackIndex: 19),
  level19(),
  level20(),
  ;

  const Music({this.retailTrackIndex, this.sharewareTrackIndex});

  final int? retailTrackIndex;
  final int? sharewareTrackIndex;

  int? trackIndexFor(GameVersion version) {
    switch (version) {
      case GameVersion.shareware:
        return sharewareTrackIndex;
      case GameVersion.retail:
      case GameVersion.spearOfDestiny:
      case GameVersion.spearOfDestinyDemo:
        return retailTrackIndex;
    }
  }

  static Music levelFor(GameVersion version, int episodeIndex, int levelIndex) {
    final route = switch (version) {
      GameVersion.shareware => _sharewareLevelRoute,
      GameVersion.retail ||
      GameVersion.spearOfDestiny ||
      GameVersion.spearOfDestinyDemo => _retailLevelRoute,
    };

    final flatIndex = switch (version) {
      GameVersion.shareware => levelIndex,
      GameVersion.retail ||
      GameVersion.spearOfDestiny ||
      GameVersion.spearOfDestinyDemo => episodeIndex * 10 + levelIndex,
    };

    final normalizedIndex = flatIndex >= 0
        ? flatIndex % route.length
        : (flatIndex % route.length + route.length) % route.length;

    return route[normalizedIndex];
  }

  static int? trackIndexForLevel(
    GameVersion version,
    int episodeIndex,
    int levelIndex,
  ) {
    return levelFor(version, episodeIndex, levelIndex).trackIndexFor(version);
  }

  static Music? fromTrackIndex(GameVersion version, int trackIndex) {
    for (final music in values) {
      if (music.trackIndexFor(version) == trackIndex) {
        return music;
      }
    }
    return null;
  }

  static const List<Music> _sharewareLevelRoute = [
    level01,
    level02,
    level03,
    level04,
    level01,
    level02,
    level03,
    level04,
    level05,
    level06,
  ];

  static const List<Music> _retailLevelRoute = [
    level01,
    level02,
    level03,
    level04,
    level01,
    level02,
    level03,
    level04,
    level05,
    level06,
    level07,
    level08,
    level09,
    level10,
    level07,
    level08,
    level10,
    level09,
    level05,
    level11,
    level12,
    level13,
    level14,
    level15,
    level12,
    level13,
    level14,
    level15,
    level16,
    level17,
    level01,
    level02,
    level03,
    level04,
    level01,
    level02,
    level03,
    level04,
    level05,
    level06,
    level07,
    level08,
    level09,
    level10,
    level07,
    level08,
    level10,
    level09,
    level05,
    level11,
    level12,
    level13,
    level14,
    level15,
    level12,
    level13,
    level14,
    level15,
    level16,
    level18,
  ];
}
