library;

import 'package:wolf_3d_dart/src/entities/entities/door.dart';
import 'package:wolf_3d_dart/src/entities/entities/weapon/weapon.dart';
import 'package:wolf_3d_dart/src/entities/entity.dart';
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';

class WeaponSaveState {
  const WeaponSaveState({
    required this.type,
    required this.state,
    required this.frameIndex,
    required this.lastFrameTime,
    required this.triggerReleased,
  });

  final WeaponType type;
  final WeaponState state;
  final int frameIndex;
  final int lastFrameTime;
  final bool triggerReleased;
}

class PlayerSaveState {
  const PlayerSaveState({
    required this.x,
    required this.y,
    required this.angle,
    required this.health,
    required this.ammo,
    required this.score,
    required this.lives,
    required this.damageFlash,
    required this.bonusFlash,
    required this.chaingunPickupFaceMsRemaining,
    required this.mutantDeathFaceActive,
    required this.godModeFaceEnabled,
    required this.faceSeed,
    required this.faceFrame,
    required this.faceCountTics,
    required this.nextFaceChangeThreshold,
    required this.hasGoldKey,
    required this.hasSilverKey,
    required this.hasMachineGun,
    required this.hasChainGun,
    required this.currentWeaponType,
    required this.weaponStates,
    required this.switchStateIndex,
    required this.pendingWeaponType,
    required this.weaponAnimOffset,
  });

  final double x;
  final double y;
  final double angle;
  final int health;
  final int ammo;
  final int score;
  final int lives;
  final double damageFlash;
  final double bonusFlash;
  final int chaingunPickupFaceMsRemaining;
  final bool mutantDeathFaceActive;
  final bool godModeFaceEnabled;
  final int faceSeed;
  final int faceFrame;
  final double faceCountTics;
  final int nextFaceChangeThreshold;
  final bool hasGoldKey;
  final bool hasSilverKey;
  final bool hasMachineGun;
  final bool hasChainGun;
  final WeaponType currentWeaponType;
  final Map<WeaponType, WeaponSaveState> weaponStates;
  final int switchStateIndex;
  final WeaponType? pendingWeaponType;
  final double weaponAnimOffset;
}

class EntitySaveState {
  const EntitySaveState({
    required this.kind,
    required this.x,
    required this.y,
    required this.spriteIndex,
    required this.angle,
    required this.state,
    required this.mapId,
    required this.lastActionTime,
    this.extraData = const <String, Object?>{},
  });

  final String kind;
  final double x;
  final double y;
  final int spriteIndex;
  final double angle;
  final EntityState state;
  final int mapId;
  final int lastActionTime;
  final Map<String, Object?> extraData;
}

class DoorSaveState {
  const DoorSaveState({
    required this.x,
    required this.y,
    required this.mapId,
    required this.state,
    required this.offset,
    required this.openTime,
  });

  final int x;
  final int y;
  final int mapId;
  final DoorState state;
  final double offset;
  final int openTime;
}

class PushwallSaveState {
  const PushwallSaveState({
    required this.x,
    required this.y,
    required this.mapId,
    required this.dirX,
    required this.dirY,
    required this.offset,
    required this.tilesMoved,
    required this.isActive,
  });

  final int x;
  final int y;
  final int mapId;
  final int dirX;
  final int dirY;
  final double offset;
  final int tilesMoved;
  final bool isActive;
}

class GameSessionSnapshot {
  const GameSessionSnapshot({
    required this.currentGameIndex,
    required this.currentEpisodeIndex,
    required this.currentLevelIndex,
    required this.returnLevelIndex,
    required this.difficulty,
    required this.timeAliveMs,
    required this.lastAcousticAlertTime,
    required this.isMapOverlayVisible,
    required this.isMenuOverlayVisible,
    required this.player,
    required this.currentLevel,
    required this.areaGrid,
    required this.areasByPlayer,
    required this.entities,
    required this.doors,
    required this.pushwalls,
  });

  final int currentGameIndex;
  final int currentEpisodeIndex;
  final int currentLevelIndex;
  final int? returnLevelIndex;
  final Difficulty difficulty;
  final int timeAliveMs;
  final int lastAcousticAlertTime;
  final bool isMapOverlayVisible;
  final bool isMenuOverlayVisible;
  final PlayerSaveState player;
  final List<List<int>> currentLevel;
  final List<List<int>> areaGrid;
  final List<bool> areasByPlayer;
  final List<EntitySaveState> entities;
  final List<DoorSaveState> doors;
  final List<PushwallSaveState> pushwalls;
}
