'use strict';

/* ────────────────────────────────────────────────────────────────
   Phase 6 Sprint 6.2 — Puzzle & Casual Templates
   
   Match-3, Block Puzzle, Physics Puzzle, Hidden Object, Card Game
──────────────────────────────────────────────────────────────── */
const DEFAULT_MATCH3_CONFIG = {
    columns: 8,
    rows: 8,
    gemTypes: 6,
    minMatch: 3,
    swapDuration: 0.2,
    fallSpeed: 12,
    scorePerGem: 10,
    comboMultiplier: 1.5,
    movesLimit: 30,
    timeLimit: 0,
    powerUpThreshold: 4,
};
function createMatch3Board(config) {
    const cells = [];
    for (let i = 0; i < config.columns * config.rows; i++) {
        cells.push(Math.floor(Math.random() * config.gemTypes));
    }
    const board = { cols: config.columns, rows: config.rows, cells };
    // Remove initial matches
    removeInitialMatches(board, config);
    return board;
}
function removeInitialMatches(board, config) {
    for (let attempts = 0; attempts < 100; attempts++) {
        const matches = findMatches(board, config.minMatch);
        if (matches.length === 0)
            break;
        for (const idx of matches) {
            board.cells[idx] = Math.floor(Math.random() * config.gemTypes);
        }
    }
}
function findMatches(board, minMatch) {
    const matched = new Set();
    // Horizontal
    for (let r = 0; r < board.rows; r++) {
        let run = 1;
        for (let c = 1; c < board.cols; c++) {
            const curr = board.cells[r * board.cols + c];
            const prev = board.cells[r * board.cols + c - 1];
            if (curr === prev && curr >= 0) {
                run++;
            }
            else {
                if (run >= minMatch) {
                    for (let k = 0; k < run; k++)
                        matched.add(r * board.cols + c - 1 - k);
                }
                run = 1;
            }
        }
        if (run >= minMatch) {
            for (let k = 0; k < run; k++)
                matched.add(r * board.cols + board.cols - 1 - k);
        }
    }
    // Vertical
    for (let c = 0; c < board.cols; c++) {
        let run = 1;
        for (let r = 1; r < board.rows; r++) {
            const curr = board.cells[r * board.cols + c];
            const prev = board.cells[(r - 1) * board.cols + c];
            if (curr === prev && curr >= 0) {
                run++;
            }
            else {
                if (run >= minMatch) {
                    for (let k = 0; k < run; k++)
                        matched.add((r - 1 - k) * board.cols + c);
                }
                run = 1;
            }
        }
        if (run >= minMatch) {
            for (let k = 0; k < run; k++)
                matched.add((board.rows - 1 - k) * board.cols + c);
        }
    }
    return Array.from(matched);
}
function removeMatches(board, indices) {
    for (const idx of indices)
        board.cells[idx] = -1;
}
function applyGravity(board, config) {
    for (let c = 0; c < board.cols; c++) {
        let writeRow = board.rows - 1;
        for (let r = board.rows - 1; r >= 0; r--) {
            const idx = r * board.cols + c;
            if (board.cells[idx] >= 0) {
                const writeIdx = writeRow * board.cols + c;
                if (writeIdx !== idx) {
                    board.cells[writeIdx] = board.cells[idx];
                    board.cells[idx] = -1;
                }
                writeRow--;
            }
        }
        // Fill empty at top
        for (let r = writeRow; r >= 0; r--) {
            board.cells[r * board.cols + c] = Math.floor(Math.random() * config.gemTypes);
        }
    }
}
function swapGems(board, idx1, idx2) {
    const tmp = board.cells[idx1];
    board.cells[idx1] = board.cells[idx2];
    board.cells[idx2] = tmp;
}
const DEFAULT_BLOCK_PUZZLE_CONFIG = {
    columns: 10,
    rows: 20,
    fallInterval: 1.0,
    lockDelay: 0.5,
    softDropMultiplier: 20,
    hardDrop: true,
    holdPiece: true,
    previewCount: 3,
    lineScores: [100, 300, 500, 800],
    levelSpeedFactor: 0.85,
    linesPerLevel: 10,
};
/** Standard tetrominoes as 4×4 bitmask rotations. */
const TETROMINOES = {
    I: [[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]],
    O: [[0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0]],
    T: [[0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
    S: [[0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
    Z: [[0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]],
    L: [[0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0]],
    J: [[0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]],
};
function createBlockPuzzleState(config) {
    const pieces = Object.keys(TETROMINOES);
    const preview = [];
    for (let i = 0; i < config.previewCount; i++) {
        preview.push(pieces[Math.floor(Math.random() * pieces.length)]);
    }
    return {
        board: new Array(config.columns * config.rows).fill(0),
        currentPiece: pieces[Math.floor(Math.random() * pieces.length)],
        currentRotation: 0,
        pieceX: Math.floor(config.columns / 2) - 2,
        pieceY: 0,
        score: 0, level: 1, lines: 0,
        heldPiece: null, preview, gameOver: false,
    };
}
function checkLines(board, cols, rows) {
    const full = [];
    for (let r = 0; r < rows; r++) {
        let complete = true;
        for (let c = 0; c < cols; c++) {
            if (board[r * cols + c] === 0) {
                complete = false;
                break;
            }
        }
        if (complete)
            full.push(r);
    }
    return full;
}
function clearLines(board, cols, lineRows) {
    // Remove lines from bottom up
    const sorted = lineRows.slice().sort((a, b) => b - a);
    for (const row of sorted) {
        // Shift everything above down
        for (let r = row; r > 0; r--) {
            for (let c = 0; c < cols; c++) {
                board[r * cols + c] = board[(r - 1) * cols + c];
            }
        }
        // Clear top row
        for (let c = 0; c < cols; c++)
            board[c] = 0;
    }
}
const DEFAULT_PHYSICS_PUZZLE_CONFIG = {
    gravity: 9.81,
    maxObjects: 20,
    goalType: 'reach',
    starThresholds: [1000, 2000, 3000],
    hintDelay: 30,
    undoSteps: 5,
};
const DEFAULT_HIDDEN_OBJECT_CONFIG = {
    timeLimit: 300,
    hintCooldown: 30,
    penaltyPerMisclick: 5,
    zoomEnabled: true,
    maxZoom: 3,
    scorePerFind: 100,
    bonusTimePerFind: 10,
};
class Deck {
    constructor(config) {
        this.cards = [];
        this.discardPile = [];
        this.cards = config.cards.slice();
        if (config.shuffled)
            this.shuffle();
    }
    shuffle() {
        for (let i = this.cards.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            const tmp = this.cards[i];
            this.cards[i] = this.cards[j];
            this.cards[j] = tmp;
        }
    }
    draw() {
        var _a;
        return (_a = this.cards.pop()) !== null && _a !== void 0 ? _a : null;
    }
    drawMultiple(count) {
        const hand = [];
        for (let i = 0; i < count; i++) {
            const card = this.draw();
            if (card)
                hand.push(card);
        }
        return hand;
    }
    discard(card) {
        this.discardPile.push(card);
    }
    reshuffleDiscard() {
        this.cards = this.cards.concat(this.discardPile);
        this.discardPile = [];
        this.shuffle();
    }
    remaining() { return this.cards.length; }
    discarded() { return this.discardPile.length; }
    peek(count = 1) {
        return this.cards.slice(-count).reverse();
    }
}
/** Create a standard 52-card deck. */
function createStandardDeck() {
    const suits = ['hearts', 'diamonds', 'clubs', 'spades'];
    const ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
    const cards = [];
    for (const suit of suits) {
        for (let i = 0; i < ranks.length; i++) {
            cards.push({
                id: `${suit}_${ranks[i]}`,
                name: `${ranks[i]} of ${suit}`,
                suit,
                rank: i + 1,
                value: Math.min(i + 1, 10), // face cards = 10
                imageId: `card_${suit}_${ranks[i].toLowerCase()}`,
                properties: {},
            });
        }
    }
    return cards;
}

exports.DEFAULT_BLOCK_PUZZLE_CONFIG = DEFAULT_BLOCK_PUZZLE_CONFIG;
exports.DEFAULT_HIDDEN_OBJECT_CONFIG = DEFAULT_HIDDEN_OBJECT_CONFIG;
exports.DEFAULT_MATCH3_CONFIG = DEFAULT_MATCH3_CONFIG;
exports.DEFAULT_PHYSICS_PUZZLE_CONFIG = DEFAULT_PHYSICS_PUZZLE_CONFIG;
exports.Deck = Deck;
exports.TETROMINOES = TETROMINOES;
exports.applyGravity = applyGravity;
exports.checkLines = checkLines;
exports.clearLines = clearLines;
exports.createBlockPuzzleState = createBlockPuzzleState;
exports.createMatch3Board = createMatch3Board;
exports.createStandardDeck = createStandardDeck;
exports.findMatches = findMatches;
exports.removeMatches = removeMatches;
exports.swapGems = swapGems;
//# sourceMappingURL=PuzzleTemplates.js.map
