'use strict';

/** 与 Unity Levels*.cs / levels-database.json spawns 一致 */

const { normalizeSpawnScale, clampScale, DEFAULT_SPAWN_SCALE } = require('./entity-spawn-defaults');
const { normalizeTexturePath } = require('./entity-texture-presets');

const SPAWN_KIND_LABELS = {
    player: '玩家',
    prop: '可拾取物',
    vehicle: '载具',
};

const DIRECTIONS = [
    'Direction.North',
    'Direction.East',
    'Direction.South',
    'Direction.West',
];

function ensureSpawns(state) {
    if (!state.config) return [];
    if (!Array.isArray(state.config.spawns)) state.config.spawns = [];
    return state.config.spawns;
}

function spawnsAt(state, x, y) {
    return ensureSpawns(state).filter((s) => s.x === x && s.y === y);
}

function findSpawnAt(state, x, y) {
    return spawnsAt(state, x, y)[0] || null;
}

function countByKind(state, kind) {
    return ensureSpawns(state).filter((s) => s.kind === kind).length;
}

function getPlayerSpawn(state) {
    return ensureSpawns(state).find((s) => s.kind === 'player') || null;
}

function getVehicleSpawn(state) {
    return ensureSpawns(state).find((s) => s.kind === 'vehicle') || null;
}

function applyScaleField(entry, scale) {
    const s = normalizeSpawnScale(scale);
    if (s !== undefined) entry.scale = s;
    else delete entry.scale;
}

function setPlayerSpawn(state, x, y, direction, scale) {
    const prev = getPlayerSpawn(state);
    const rest = ensureSpawns(state).filter((s) => s.kind !== 'player');
    const entry = {
        x,
        y,
        kind: 'player',
        playerDirection: direction || 'Direction.South',
    };
    const sc = scale !== undefined ? scale : prev?.scale ?? DEFAULT_SPAWN_SCALE.player;
    applyScaleField(entry, sc);
    rest.push(entry);
    state.config.spawns = rest;
    return entry;
}

function setVehicleSpawn(state, x, y, direction, scale) {
    const prev = getVehicleSpawn(state);
    const rest = ensureSpawns(state).filter((s) => s.kind !== 'vehicle');
    const entry = {
        x,
        y,
        kind: 'vehicle',
        vehicleDirection: direction || 'Direction.North',
    };
    const sc = scale !== undefined ? scale : prev?.scale ?? DEFAULT_SPAWN_SCALE.vehicle;
    applyScaleField(entry, sc);
    rest.push(entry);
    state.config.spawns = rest;
    return entry;
}

function clearVehicleSpawn(state) {
    const before = countByKind(state, 'vehicle');
    state.config.spawns = ensureSpawns(state).filter((s) => s.kind !== 'vehicle');
    return before > 0;
}

/** 载具 0 或 1：再次点击已有载具格则清除 */
function vehicleToggleInternal(state, x, y, direction, scale) {
    const existing = getVehicleSpawn(state);
    if (existing && existing.x === x && existing.y === y) {
        clearVehicleSpawn(state);
        return { changed: false, spawn: null, removed: true };
    }
    const spawn = setVehicleSpawn(state, x, y, direction, scale);
    return { changed: true, spawn, removed: false };
}

function toggleVehicleSpawn(state, x, y, direction, scale) {
    const r = vehicleToggleInternal(state, x, y, direction, scale);
    return r.changed;
}

function toggleVehicleSpawnDetailed(state, x, y, direction, scale) {
    return vehicleToggleInternal(state, x, y, direction, scale);
}

function togglePropSpawn(state, x, y, scale, propPlacement) {
    const spawns = ensureSpawns(state);
    const idx = spawns.findIndex((s) => s.x === x && s.y === y && s.kind === 'prop');
    if (idx >= 0) {
        spawns.splice(idx, 1);
        return { changed: false, spawn: null, removed: true };
    }
    const entry = { x, y, kind: 'prop' };
    if (propPlacement === 'ground') entry.propPlacement = 'ground';
    const sc = scale !== undefined ? scale : DEFAULT_SPAWN_SCALE.prop;
    applyScaleField(entry, sc);
    spawns.push(entry);
    return { changed: true, spawn: entry, removed: false };
}

function removeSpawnAt(state, x, y) {
    const spawns = ensureSpawns(state);
    const before = spawns.length;
    state.config.spawns = spawns.filter((s) => !(s.x === x && s.y === y));
    return state.config.spawns.length < before;
}

function removeSpawnRef(state, spawnRef) {
    if (!spawnRef) return false;
    const spawns = ensureSpawns(state);
    const idx = spawns.indexOf(spawnRef);
    if (idx < 0) return false;
    spawns.splice(idx, 1);
    return true;
}

function pickSpawnAtCell(state, x, y, preferKind) {
    const hits = spawnsAt(state, x, y);
    if (!hits.length) return null;
    if (preferKind) {
        const m = hits.find((s) => s.kind === preferKind);
        if (m) return m;
    }
    return hits[0];
}

function spawnStillExists(state, spawnRef) {
    if (!spawnRef) return false;
    return ensureSpawns(state).includes(spawnRef);
}

function updateSpawnEntry(state, spawnRef, patch) {
    const spawns = ensureSpawns(state);
    const idx = spawns.indexOf(spawnRef);
    if (idx < 0) return false;
    const cur = { ...spawns[idx] };
    if (patch.x !== undefined) cur.x = parseInt(patch.x, 10);
    if (patch.y !== undefined) cur.y = parseInt(patch.y, 10);
    if (patch.playerDirection !== undefined) cur.playerDirection = patch.playerDirection;
    if (patch.vehicleDirection !== undefined) cur.vehicleDirection = patch.vehicleDirection;
    if (patch.scale !== undefined) applyScaleField(cur, patch.scale);
    if (patch.texture !== undefined) {
        const t = normalizeTexturePath(patch.texture);
        if (t) cur.texture = t;
        else delete cur.texture;
    }
    spawns[idx] = cur;
    return true;
}

function formatSpawnScale(spawn) {
    if (spawn?.scale !== undefined && spawn.scale !== null) return spawn.scale;
    return 1;
}

function validateSpawns(state) {
    const spawns = ensureSpawns(state);
    const players = spawns.filter((s) => s.kind === 'player');
    const vehicles = spawns.filter((s) => s.kind === 'vehicle');
    const props = spawns.filter((s) => s.kind === 'prop');
    const errors = [];
    if (players.length !== 1) {
        errors.push(`玩家必须恰好 1 个（当前 ${players.length}）`);
    }
    if (vehicles.length > 1) {
        errors.push(`载具最多 1 个（当前 ${vehicles.length}）`);
    }
    if (props.length < 1) {
        errors.push(`可拾取物至少 1 个（当前 ${props.length}）`);
    }
    return { ok: errors.length === 0, errors, players, vehicles, props };
}

function spawnSummary(state) {
    const v = validateSpawns(state);
    const player = v.players[0];
    const vehicle = v.vehicles[0];
    const parts = [];
    if (player) {
        const sc = formatSpawnScale(player);
        parts.push(`玩家 (${player.x},${player.y}) ${player.playerDirection || ''}${sc !== 1 ? ` ×${sc}` : ''}`);
    } else {
        parts.push('玩家 未设置');
    }
    parts.push(`载具 ${v.vehicles.length}/1`);
    if (vehicle) {
        const sc = formatSpawnScale(vehicle);
        parts.push(`@(${vehicle.x},${vehicle.y}) ${vehicle.vehicleDirection || ''}${sc !== 1 ? ` ×${sc}` : ''}`);
    }
    parts.push(`可拾取物 ${v.props.length} 个`);
    if (!v.ok) parts.push('[待完善]');
    return parts.join(' · ');
}

function validationHint(state) {
    const v = validateSpawns(state);
    if (v.ok) return '';
    return v.errors.join('；');
}

module.exports = {
    SPAWN_KIND_LABELS,
    DIRECTIONS,
    DEFAULT_SPAWN_SCALE,
    clampScale,
    ensureSpawns,
    spawnsAt,
    findSpawnAt,
    countByKind,
    getPlayerSpawn,
    getVehicleSpawn,
    setPlayerSpawn,
    setVehicleSpawn,
    clearVehicleSpawn,
    toggleVehicleSpawn,
    toggleVehicleSpawnDetailed,
    togglePropSpawn,
    removeSpawnAt,
    removeSpawnRef,
    pickSpawnAtCell,
    spawnStillExists,
    updateSpawnEntry,
    formatSpawnScale,
    validateSpawns,
    spawnSummary,
    validationHint,
};
