"""Per-project settings for the Unity level import, read from `tools/unity-import.json`.

Every value that belongs to a particular game — where its Unity project lives, which scene is the
level, which MonoBehaviour scripts mark spawns and bases, where the play plane sits — comes from
this one file, so the scripts themselves never need editing to run on another game. Copy
`unity-import.example.json` to `unity-import.json` and fill it in; the keys and their defaults are
listed in DEFAULTS. `UNITY_IMPORT_CONFIG` names a different file; `UNITY_ROOT`, `UNITY_PLANE_Z` and
`UNITY_AXIS_OVERRIDE` override single values from the environment for experiments.
"""
import json
import os

_HERE = os.path.dirname(os.path.abspath(__file__))

DEFAULTS = {
    # The Unity tree that holds Assets/ and ProjectSettings/ for the level (a repo can hold more
    # than one; pick the one the creator's editor opens).
    'unityRoot': '',
    # Scene path relative to unityRoot, and the level name the game data is written under.
    'scene': 'Assets/Scenes/Main.unity',
    'levelName': 'Main',
    # Gameplay plane for a 2D-on-a-plane game: Unity z of the plane and the half-thickness a
    # collider must cross to count as a wall (the ship's radius is a good value).
    'planeZ': -1.0,
    'planeHalf': 0.8,
    # Instances farther than this from the origin are stray copies parked outside the level.
    'arenaLimit': 80.0,
    # Output GLB (from convert_assets) and the asset name it is uploaded under.
    'glb': 'build/glb/level.glb',
    'assetName': 'level-arena',
    # Where write_arena_data emits the game's level data.
    'outputTs': 'src/work/ArenaData.ts',
    # Prefabs to convert when convert_assets is not run in scene mode.
    'prefabs': [],
    # Prefab tags whose colliders are never walls (decoration that would seal a room).
    'badTags': [],
    # MonoBehaviour scripts (file names) and prefab files that mark spawns, bases and pickups.
    'markerScripts': ['Spawner.cs', 'SpawnPoint.cs', 'PowerupSpawnPoint.cs'],
    'markerPrefabs': ['Base.prefab', 'Spawner.prefab', 'SpawnPoint.prefab', 'PowerupSpawnPoint.prefab'],
    # Render-mesh name families that must be solid although they carry no 2D collider
    # (mesh_walls slices them at the play plane).
    'wallFamilies': [],
    # Per-pack axis override for experiments: "Pack=cycYZX:-1,1,1;Other=identity".
    'axisOverride': '',
}


def _load():
    path = os.environ.get('UNITY_IMPORT_CONFIG') or os.path.join(_HERE, 'unity-import.json')
    cfg = dict(DEFAULTS)
    if os.path.exists(path):
        with open(path, encoding='utf-8') as fh:
            data = json.load(fh)
        unknown = sorted(set(data) - set(DEFAULTS) - {'_comment'})
        if unknown:
            raise SystemExit(f'{path}: unknown keys {unknown}; known keys are {sorted(DEFAULTS)}')
        cfg.update({k: v for k, v in data.items() if k != '_comment'})
    if os.environ.get('UNITY_ROOT'):
        cfg['unityRoot'] = os.environ['UNITY_ROOT']
    if os.environ.get('UNITY_PLANE_Z'):
        cfg['planeZ'] = float(os.environ['UNITY_PLANE_Z'])
    if os.environ.get('UNITY_AXIS_OVERRIDE'):
        cfg['axisOverride'] = os.environ['UNITY_AXIS_OVERRIDE']
    cfg['unityRoot'] = os.path.expanduser(cfg['unityRoot'])
    cfg['_path'] = path
    return cfg


CFG = _load()


def unity_root():
    root = CFG['unityRoot']
    if not root or not os.path.isdir(os.path.join(root, 'Assets')):
        raise SystemExit(f"unityRoot {root!r} has no Assets/ directory; set it in {CFG['_path']} "
                         f"(or UNITY_ROOT) to the Unity tree that holds the level")
    return root


def scene_path():
    return os.path.join(unity_root(), CFG['scene'])


def project_root():
    """The game project (the directory that holds tools/)."""
    return os.path.dirname(_HERE)
