using System;
using System.Collections.Generic;
using UnityEngine;
namespace Heroes.Battle
{
///
/// Container of all obstacles and per-terrain background sprites used by
/// the generator and the view. Generator reads it as pure data; view uses
/// it to resolve sprites during deployment.
///
[CreateAssetMenu(menuName = "Heroes/Battle/Obstacle Database", fileName = "ObstacleDatabase")]
public sealed class ObstacleDatabase : ScriptableObject
{
[Tooltip("All known obstacles. Filtered by allowed terrain at generation time.")]
public List obstacles = new List();
[Tooltip("Background sprite variants for each terrain. Generator picks one at random.")]
public List backgrounds = new List();
[Header("Generation")]
[Tooltip("Inclusive minimum number of usual obstacles to attempt.")]
[Min(0)]
public int minObstacles = 5;
[Tooltip("Inclusive maximum number of usual obstacles to attempt.")]
[Min(0)]
public int maxObstacles = 15;
[Tooltip("Placement retry attempts per obstacle. H3 gives up after a handful of tries.")]
[Min(1)]
public int placementAttemptsPerObstacle = 20;
[Tooltip("Probability (0..1) of placing an absolute obstacle when one is available for the terrain.")]
[Range(0f, 1f)]
public float absoluteObstacleChance = 0.5f;
public IEnumerable GetObstaclesForTerrain(TerrainType terrain)
{
return GetObstaclesForTerrain(terrain, null);
}
public IEnumerable GetObstaclesForTerrain(TerrainType terrain, ObstacleType? typeFilter)
{
if (obstacles == null) yield break;
foreach (var o in obstacles)
{
if (o == null) continue;
if (typeFilter.HasValue && o.type != typeFilter.Value) continue;
if (o.allowedTerrains == null || o.allowedTerrains.Count == 0) continue;
if (o.allowedTerrains.Contains(terrain)) yield return o;
}
}
public TerrainBackground FindBackgrounds(TerrainType terrain)
{
if (backgrounds == null) return null;
foreach (var b in backgrounds)
{
if (b != null && b.terrain == terrain) return b;
}
return null;
}
public ObstacleDefinition FindById(string obstacleId)
{
if (obstacles == null || string.IsNullOrEmpty(obstacleId)) return null;
foreach (var o in obstacles)
{
if (o != null && o.ResolveId() == obstacleId) return o;
}
return null;
}
}
[Serializable]
public sealed class TerrainBackground
{
public TerrainType terrain;
[Tooltip("One or more sprite variants. Generator picks one at random.")]
public List variants = new List();
public string ResolveVariantId(int index)
{
if (variants == null || variants.Count == 0) return terrain.ToString();
index = Mathf.Clamp(index, 0, variants.Count - 1);
var s = variants[index];
return s != null ? s.name : $"{terrain}#{index}";
}
public Sprite GetVariantById(string id)
{
if (variants == null) return null;
foreach (var s in variants)
{
if (s != null && s.name == id) return s;
}
return variants.Count > 0 ? variants[0] : null;
}
}
}