/**
 * Атмосферные частицы (v1 Atmosphere): тёплые мотыльки над лугами
 * (светятся цветом, дрейф по синусу) и дымка прудов (серые клочья,
 * якорятся на клетки воды и медленно бродят на месте). Voxel-облако,
 * позы — детерминированные синусы от времени цикла, гейт-стабильно.
 */
import type { VoxelCloud, VoxelRenderer } from '@rpg/engine';
import type { WaterCell } from './waterShimmer';

/** Профиль частиц области. */
export type AmbientKind = 'moths' | 'fog';

const MOTH_COUNT = 10;
const MOTH_COLORS = ['#f0d878', '#d8b050']; // B-тёплые: только «жизнь»
const FOG_COUNT = 22;
const FOG_COLOR = '#a7b3bd'; // светлее воды — клочья читаются туманом
const RADIUS = 30; // половина ширины облака мотыльков вокруг камеры (как пепел)
/** Клок тумана: квадрат 2×2 вокселя ЛЕЖИТ на воде (как полупрозрачные
 *  пятна v1 — непрозрачный куб в воздухе читался бы «ящиком»). */
const FOG_TILE: readonly (readonly [number, number])[] = [[0, 0], [1, 0], [0, 1], [1, 1]];
/** Сдвиг клочьев из плоскости куба воды — против z-fighting копланарных
 *  граней на кромках (как у бликов шиммера, EPS 0.03). */
const FOG_EPS = 0.03;

export class AmbientParticles {
    private readonly cloud: VoxelCloud;

    constructor(
        renderer: VoxelRenderer,
        private readonly kind: AmbientKind,
        /** Клетки поверхности воды — якоря клочьев дымки (только для fog). */
        private readonly cells: readonly WaterCell[] = [],
    ) {
        this.cloud = renderer.addVoxelCloud([]);
        this.cloud.mesh.castShadow = false; // частицы не бросают теней
    }

    /** Снапшот для моста: профиль и число частиц (у мотыльков всегда видимы). */
    get info(): { kind: AmbientKind; count: number } {
        return {
            kind: this.kind,
            count: this.kind === 'moths' ? MOTH_COUNT : this.cells.length ? FOG_COUNT * FOG_TILE.length : 0,
        };
    }

    /** Поза облака: цель камеры и время цикла (детерминизм гейтов). */
    update(t: number, target: readonly [number, number, number]): void {
        const voxels: { pos: [number, number, number]; color: string }[] = [];
        if (this.kind === 'moths') {
            for (let i = 0; i < MOTH_COUNT; i++) {
                const p = i * 2.399; // золотое сечение: разброс фаз
                // кружение вокруг камеры: медленный орбитальный дрейф
                const x = target[0] + Math.sin(t * 0.13 + p) * RADIUS * 0.8;
                const z = target[2] + Math.cos(t * 0.11 + p * 1.7) * RADIUS * 0.8;
                // полёт: плавная волна над травой + трепет
                const y = 4.5 + Math.sin(t * 0.4 + p * 2) * 2.2;
                voxels.push({
                    pos: [x + Math.sin(t * 1.7 + p) * 0.6, y, z + Math.cos(t * 1.5 + p) * 0.6],
                    color: MOTH_COLORS[i % MOTH_COLORS.length]!,
                });
            }
        } else {
            // клочья дымят НА воде: якорь — клетка поверхности, медленное
            // блуждание на месте (без якорей — клочьев нет: дымка только прудам)
            const n = this.cells.length;
            for (let i = 0; i < FOG_COUNT && n > 0; i++) {
                const p = i * 2.399;
                const a = this.cells[(i * 131) % n]!; // 131 взаимно прост с длиной — разброс
                const x = a.x + Math.sin(t * 0.05 + p) * 2.5;
                const z = a.z + Math.cos(t * 0.04 + p * 1.3) * 2.5;
                for (const [dx, dz] of FOG_TILE) {
                    voxels.push({ pos: [x + dx + FOG_EPS, 2.56, z + dz + FOG_EPS], color: FOG_COLOR });
                }
            }
        }
        this.cloud.update(voxels);
        this.cloud.mesh.castShadow = false; // пересоздание облака возвращает тень
    }

    /** Скрыть облако (мост setAsh / смена профиля). */
    hide(): void {
        this.cloud.update([]);
    }

    dispose(): void {
        this.cloud.dispose();
    }
}