/**
 * qix_core.js
 * ゲームの基本定数とグリッドシステム
 */
const CONFIG = {
    CANVAS_SIZE: 600,
    GRID_SIZE: 1, 

    STATE: {
        EMPTY: 0,
        WALL: 1, 
        TRAIL: 2 
    },

    MAX_MP: 100,
    COST_PER_PIXEL: 0.075,
    BOOST_COST: 40,
    BOOST_SPEED_MULTI: 2.5
};

class GridSystem {
    constructor() {
        this.cols = CONFIG.CANVAS_SIZE / CONFIG.GRID_SIZE;
        this.rows = CONFIG.CANVAS_SIZE / CONFIG.GRID_SIZE;
        this.data = [];
        this.reset();
    }

    reset() {
        this.data = new Uint8Array(this.cols * this.rows);
        for (let y = 0; y < this.rows; y++) {
            for (let x = 0; x < this.cols; x++) {
                const isBorder = (x === 0 || x === this.cols - 1 || y === 0 || y === this.rows - 1);
                if (isBorder) {
                    this.set(x, y, CONFIG.STATE.WALL);
                }
            }
        }
    }

    isValid(x, y) {
        return x >= 0 && x < this.cols && y >= 0 && y < this.rows;
    }

    get(x, y) {
        if (!this.isValid(x, y)) return null;
        return this.data[y * this.cols + x];
    }

    set(x, y, val) {
        if (this.isValid(x, y)) {
            this.data[y * this.cols + x] = val;
        }
    }

    hasAdjacentEmpty(cx, cy) {
        for (let dy = -1; dy <= 1; dy++) {
            for (let dx = -1; dx <= 1; dx++) {
                if (dx === 0 && dy === 0) continue;
                const nx = cx + dx;
                const ny = cy + dy;
                if (this.isValid(nx, ny)) {
                    if (this.data[ny * this.cols + nx] === CONFIG.STATE.EMPTY) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    processSplit(trailPoints, enemies) {
        const convertedIndices = [];
        
        trailPoints.forEach(p => {
            if (this.isValid(p.x, p.y)) {
                const idx = p.y * this.cols + p.x;
                if (this.data[idx] !== CONFIG.STATE.WALL) {
                    this.data[idx] = CONFIG.STATE.WALL;
                    convertedIndices.push(idx);
                }
            }
        });

        let visited = new Uint8Array(this.cols * this.rows);
        let regions = [];
        
        const dirOffsets = [
            { dx: 1, dy: 0 }, { dx: -1, dy: 0 },
            { dx: 0, dy: 1 }, { dx: 0, dy: -1 }
        ];

        let seeds = [];
        trailPoints.forEach(p => {
            dirOffsets.forEach(offset => {
                const nx = p.x + offset.dx;
                const ny = p.y + offset.dy;
                if (this.isValid(nx, ny)) {
                    const nIdx = ny * this.cols + nx;
                    if (this.data[nIdx] === CONFIG.STATE.EMPTY) {
                        seeds.push(nIdx);
                    }
                }
            });
        });

        for (let seedIdx of seeds) {
            if (visited[seedIdx]) continue;

            let cells = [];
            let stack = [seedIdx];
            visited[seedIdx] = 1;
            cells.push(seedIdx);

            while (stack.length > 0) {
                let idx = stack.pop();
                let cx = idx % this.cols;
                let cy = Math.floor(idx / this.cols);

                for (let offset of dirOffsets) {
                    let nx = cx + offset.dx;
                    let ny = cy + offset.dy;

                    if (nx >= 0 && nx < this.cols && ny >= 0 && ny < this.rows) {
                        let nIdx = ny * this.cols + nx;
                        if (!visited[nIdx]) {
                            if (this.data[nIdx] === CONFIG.STATE.EMPTY) {
                                visited[nIdx] = 1;
                                cells.push(nIdx);
                                stack.push(nIdx);
                            }
                        }
                    }
                }
            }
            regions.push(cells);
        }

        if (regions.length < 2) {
            console.warn("Split Failed: Reverting walls.");
            convertedIndices.forEach(idx => {
                this.data[idx] = CONFIG.STATE.EMPTY;
            });
            // 失敗時は空のデータを返す
            return { claimedCount: 0, trappedEnemies: [], filledIndices: [] };
        }

        regions.sort((a, b) => a.length - b.length);
        
        let claimedCount = 0;
        let filledIndices = []; // ★追加: 今回確保された全セルのインデックス

        // 小さい領域を埋める
        for (let i = 0; i < regions.length - 1; i++) {
            let regionIndices = regions[i];
            for(let idx of regionIndices) {
                this.data[idx] = CONFIG.STATE.WALL;
                claimedCount++;
                filledIndices.push(idx); // ★追加
            }
        }

        let trappedEnemies = enemies.filter(e => {
            const gx = Math.floor(e.x / CONFIG.GRID_SIZE);
            const gy = Math.floor(e.y / CONFIG.GRID_SIZE);
            const idx = gy * this.cols + gx;

            if (e.type === 'SPARKS') {
                return !this.hasAdjacentEmpty(gx, gy);
            } else {
                return this.data[idx] === CONFIG.STATE.WALL;
            }
        });
        
        claimedCount += trailPoints.length;
        
        // 線だった場所も「確保領域」として扱う
        trailPoints.forEach(p => {
             const idx = p.y * this.cols + p.x;
             filledIndices.push(idx);
        });

        // ★修正: filledIndices を戻り値に追加
        return { claimedCount, trappedEnemies, filledIndices };
    }
}