import { writeBufferGeometryRange } from './attribute';
import { ColorFormat } from './buf/draw/v1/metadata_pb';
import { traits } from './ecs';
import {} from './metadata';
export const createChunkLoader = ({ world, invalidate, fetchChunk, colorFormat = ColorFormat.RGB, }) => {
    const active = new Set();
    const controller = new AbortController();
    const pull = async (uuid, entity, total, firstChunkEnd) => {
        if (active.has(uuid))
            return;
        active.add(uuid);
        const { signal } = controller;
        let nextStart = firstChunkEnd;
        try {
            while (!signal.aborted) {
                const chunk = await fetchChunk(uuid, nextStart, signal);
                if (signal.aborted || !chunk)
                    break;
                const buffer = entity.get(traits.BufferGeometry);
                if (!buffer)
                    break;
                writeBufferGeometryRange(buffer, chunk.positions, chunk.start, {
                    colorFormat,
                    colors: chunk.colors,
                    opacities: chunk.opacities,
                });
                const chunkElements = chunk.positions.length / 3;
                nextStart = chunk.start + chunkElements;
                entity.set(traits.ChunkProgress, { loaded: nextStart, total });
                invalidate();
                if (chunk.done)
                    break;
            }
        }
        catch (error) {
            if (!signal.aborted) {
                console.error(`Chunk pull failed for entity ${uuid}:`, error);
            }
        }
        finally {
            active.delete(uuid);
            if (world.has(entity)) {
                entity.remove(traits.ChunkProgress);
            }
        }
    };
    return {
        start(uuid, entity, metadata) {
            const chunks = metadata.chunks;
            if (!chunks || chunks.total <= 0)
                return;
            entity.add(traits.ChunkProgress({ loaded: chunks.chunkSize, total: chunks.total }));
            void pull(uuid, entity, chunks.total, chunks.chunkSize);
        },
        dispose() {
            controller.abort();
        },
    };
};
