import { LEVEL_CONFIG } from './config.js';

export class GameScene extends Phaser.Scene {
    constructor() {
        super({ key: 'GameScene' });

        this.gridConfig = {
            allPadding: 50,
            leftPadding: 700,
            rows: 8,
            cols: 8,
            jewelWidth: 100,
            jewelHeight: 100,
        };

        // Stats
        this.numberOfJewels = 4;
        this.startRows = 5;
        this.level = 1;
        this.matchesNeeded = 8;
        this.score = 0;
        this.ally = 'goblin';
        this.spritePlus = 0;
        this.gridColor = 0x000000;

        // Status Indication
        this.isDropping = false;
        this.isSwapping = false;
        this.isDestroying = false;
        this.isMovingUp = false;
        this.isPlayingVideo = false;
        this.isPlayingAudio = false;
        this.gameStatus = true;
        this.rowOne = false;
        
        // Add selectedJewel property
        this.selectedJewel = null;
        this.swapWithJewel = null;

        // Timer properties
        this.moveTimer = 0;
        this.moveInterval = 12000;
        this.timerText = null;
        this.countdownTimer = false;
    }

    preload() {
        // Jewels
        this.load.spritesheet('jewels', 'assets/jewels.png', {
            frameWidth: 100,
            frameHeight: 100
        });
        
        // Fonts
        this.load.font('cruiser', 'assets/NEUROPOL.ttf');
        this.load.font('code', 'assets/CodePredators-Regular.otf');

        // Music
        this.load.audio('clear', 'assets/clear.mp3');
        this.load.audio('level-up', 'assets/level-up.mp3');
        this.load.audio('level-complete', 'assets/level-complete.mp3');
        this.load.audio('switch', 'assets/switch.mp3');
        this.load.audio('game-over', 'assets/game-over-boom.mp3');
        this.load.audio('countdown', 'assets/countdown.mp3');
        this.load.audio('alarm', 'assets/alarm.mp3');

        // Ally Assets
        const allys = ['goblin', 'surfer', 'bear'];
        allys.forEach((ally) => {
            this.load.video(`${ally}-resting`, `assets/${ally}-resting.mp4`);
            this.load.video(`${ally}-excited`, `assets/${ally}-excited.mp4`);
            this.load.video(`${ally}-pleased`, `assets/${ally}-pleased.mp4`);
            this.load.video(`${ally}-match`, `assets/${ally}-match.mp4`);
            this.load.video(`${ally}-background`, `assets/${ally}-background.mp4`);
            this.load.audio(`${ally}-a1`, `assets/${ally}-a1.mp3`);
            this.load.audio(`${ally}-a2`, `assets/${ally}-a2.mp3`);
            this.load.audio(`${ally}-a3`, `assets/${ally}-a3.mp3`);
            this.load.audio(`${ally}-b`, `assets/${ally}-b.mp3`);
            this.load.audio(`${ally}-c`, `assets/${ally}-c.mp3`);
            this.load.audio(`${ally}-intro`, `assets/${ally}-intro.mp3`);
            this.load.audio(`${ally}-outro`, `assets/${ally}-outro.mp3`);
            this.load.audio(`${ally}-music`, `assets/${ally}-music.mp3`);
        });
    }

    create() {
        // Set Start Level
        const newLevel = LEVEL_CONFIG[this.level];
        this.numberOfJewels = newLevel.numberOfJewels;
        this.matchesNeeded = newLevel.matchesNeeded;
        this.moveInterval = newLevel.moveInterval;
        this.ally = newLevel.ally;
        this.spritePlus = newLevel.spritePlus;
        this.gridColor = newLevel.gridColor;

        // Background Video
        this.bgVideo = this.add.video(0, 0, `${this.ally}-background`);
        this.bgVideo.setOrigin(0);
        console.log("width",this.scale.width);
        this.bgVideo.scaleX = this.scale.width / 848;
        this.bgVideo.scaleY = this.scale.height / 480;
        this.bgVideo.play(true);

        // Create the Game Grid
        this.makeGrid(this.gridColor);
        this.physics.world.setBounds(this.grid.getBounds().x - 50, this.grid.getBounds().y - 50, this.grid.getBounds().width + 100, this.grid.getBounds().height + 100);
        this.jewels = this.physics.add.group({
            collideWorldBounds: true,
        });
        this.physics.add.collider(this.jewels, this.jewels);
        this.createStart();

        // Background Music
        this.bgMusic = this.sound.add(`${this.ally}-music`, { volume: 0.2 });
        this.bgMusic.loop = true;
        this.bgMusic.play();

        // Create Ally Video
        this.allyVideo = this.add.video(350, 610, `${this.ally}-resting`).setOrigin(0.5);
        this.allyVideo.play(true);
        this.allyVideo.postFX.addGlow();
        this.time.delayedCall(500, () => {
            this.sound.play(`${this.ally}-intro`);
        });

        // Create Text Background
        this.add.rectangle(10, 40, 650, 270, 0x000000, .5).setOrigin(0);
        
        // Create the score text
        this.scoreText = this.add.text(20, 50, 'Score: 0', {
            fontFamily: 'cruiser, arial',
            fontSize: '36px',
            fill: '#ffffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0);

        // Create the Level text
        this.LevelText = this.add.text(20, 116, `Level: ${this.level}`, {
            fontFamily: 'cruiser, arial',
            fontSize: '36px',
            fill: '#ffffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0);

        // Create the timer text
        this.timerText = this.add.text(20, 182, 'Next Row:', {
            fontFamily: 'cruiser, arial',
            fontSize: '36px',
            fill: '#ffffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0);

        // Create the Matches Needed text
        this.matchesText = this.add.text(20, 248, `Remaining Matches: ${this.matchesNeeded}`, {
            fontFamily: 'cruiser, arial',
            fontSize: '36px',
            fill: '#ffffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0);
    }

    update(time, delta) {
        // Update the move timer
        this.moveTimer += delta;
        
        // Check if it's time to move all jewels up
        if (
                this.moveTimer >= this.moveInterval && 
                this.isDropping === false && 
                this.isSwapping === false && 
                this.isDestroying === false &&
                this.gameStatus === true
            ) {
            this.moveAllJewelsUp();
            this.moveTimer = 0; // Reset the timer
        }

        if (this.moveInterval - this.moveTimer <= 3000) {
            this.startCountdownTimer();
        }
        
        // Update the timer display
        const timeRemaining = (this.moveInterval - this.moveTimer) / 1000;
        const displayTime = timeRemaining.toFixed(2);
        if (this.timerText) {
            this.timerText.setText(`Next Row: ${displayTime}`);
        }
    }

    startCountdownTimer() {
        if (this.countdownTimer === true || this.gameStatus === false) {
            return;
        }

        this.countdownTimer = true;
        this.sound.play('countdown');
        this.time.delayedCall(6000, () => {
            this.countdownTimer = false;
        });
    }

    makeGrid(gridColor = 0x000000) {
        this.grid = this.add.rectangle(
            this.gridConfig.leftPadding + this.gridConfig.allPadding, 
            0 + this.gridConfig.allPadding, 
            this.gridConfig.cols * this.gridConfig.jewelWidth, 
            this.gridConfig.rows*this.gridConfig.jewelHeight, 
            gridColor,
            .5
        ).setOrigin(0);
        this.grid.setInteractive();
        this.grid.on('pointerdown', (pointer) => {
            this.handleGridClick(pointer.x, pointer.y);
        });
    }

    createJewel(type, col, row) {
        // Create a jewel sprite from the spritesheet using the type as frame index
        const jewel = this.physics.add.sprite(
            col * this.gridConfig.jewelWidth + this.gridConfig.leftPadding, 
            row * this.gridConfig.jewelHeight, 
            'jewels', 
            type + this.spritePlus
        );
        jewel.setOrigin(0.5);
        jewel.setDisplaySize(this.gridConfig.jewelWidth, this.gridConfig.jewelHeight);
        jewel.jewelType = type;
        this.jewels.add(jewel);
        
        // Add click event to the jewel
        jewel.setInteractive();
        jewel.on('pointerdown', () => {
            this.handleJewelClick(jewel.x, jewel.y);
        });
        
        return jewel;
    }

    createStart() {
        // Create jewels at the bottom of the grid
        let createWait = 0;
        const startRow = this.gridConfig.rows - this.startRows;
        
        for (let row = this.startRows; row > 0; row--) {
            for (let col = 1; col <= this.gridConfig.cols; col++) {
                let type = null;
                let match = false;

                do {
                    type = Phaser.Math.Between(0, this.numberOfJewels - 1)
                    match = false; 

                    if (this.getJewelAtPosition(col-1, startRow + row) === type && 
                    this.getJewelAtPosition(col-2, startRow + row) === type) {
                        match = true;
                    }

                    if (this.getJewelAtPosition(col, startRow + row + 1) === type &&
                    this.getJewelAtPosition(col, startRow + row + 2) === type) {
                        match = true;
                    }
                } while (match === true);
                
                // Create the jewel at the correct position
                this.createJewel(type, col, startRow + row);
            }
        }
    }

    getJewelAtPosition(col, row) {
        // Convert grid coordinates to world coordinates
        const x = col * this.gridConfig.jewelWidth + this.gridConfig.leftPadding;
        const y = row * this.gridConfig.jewelHeight;
        
        // Find the jewel at that position
        let jewelAtPosition = null;
        
        // Iterate through all jewels to find one near the specified position
        this.jewels.children.iterate((jewel) => {
            if (jewel && 
                Math.abs(jewel.x - x) < this.gridConfig.jewelWidth / 2 &&
                Math.abs(jewel.y - y) < this.gridConfig.jewelHeight / 2) {
                jewelAtPosition = jewel;
                return false; // Stop iteration
            }
        });
        
        // Return the jewel type or null if not found
        return jewelAtPosition ? jewelAtPosition.jewelType : null;
    }

    // Handle clicks on the grid
    handleGridClick(x, y) {
        if (!this.selectedJewel) {
            return;
        }

        const selectedX = this.selectedJewel.x;
        const selectedY = this.selectedJewel.y;
        
        // Calculate which grid tile was clicked
        const clickCol = Math.floor((x+50) / this.gridConfig.jewelWidth);
        const clickRow = Math.floor((y+50) / this.gridConfig.jewelHeight);
        
        // Calculate selected jewel's grid position
        const selectedCol = Math.floor(selectedX / this.gridConfig.jewelWidth);
        const selectedRow = Math.floor(selectedY / this.gridConfig.jewelHeight);
        
        // Check if click is adjacent (up, down, left, right)
        const isAdjacent = 
            (clickCol === selectedCol && Math.abs(clickRow - selectedRow) === 1) ||  // Up or down
            (clickRow === selectedRow && Math.abs(clickCol - selectedCol) === 1);   // Left or right
            
        if (isAdjacent) {
            this.tweens.add({
                targets: this.selectedJewel,
                scale: 1,
                duration: 200
            });
            this.moveJewel(clickCol * this.gridConfig.jewelWidth, clickRow * this.gridConfig.jewelHeight);          
        }
    }

    // Modified swap function to disable clicks during execution
    moveJewel(x ,y) {
        if (this.isMovingUp === true) {
            this.time.delayedCall(1000, ()=> {
                this.moveJewel(x, y);
            })
            return;
        }
        // Set swapping flag to prevent new clicks from being processed
        this.isSwapping = true;
        this.sound.play('switch');
        
        // Disable all jewel interactivity temporarily 
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                jewel.disableInteractive();
            }
        });
        
        // Perform the swap animation here - currently empty
        const fromX = this.selectedJewel.x;
        const fromY = this.selectedJewel.y;
        const toX = x;
        const toY = y;
        this.tweens.add({
            targets: this.selectedJewel,
            x: toX,
            y: toY,
            duration: 300,
            onComplete: () => {
                this.dropJewels();
                this.time.delayedCall(300, () => {
                    this.checkMatches();
                })
            }
        });
        this.selectedJewel = null;
        this.swapWithJewel = null;
        

        // After swap completes, re-enable interactivity and reset flag
        this.time.delayedCall(300, () => { // Adjust delay as needed for animation duration
            this.jewels.children.iterate((jewel) => {
                if (jewel) {
                    jewel.setInteractive();
                }
            });
            
            this.isSwapping = false;
        });
    }
    
    // New function to handle jewel clicks
    handleJewelClick(x, y) {
        // Find which jewel was clicked
        const clickedJewel = this.getJewelAtWorldPosition(x, y);
        
        //const isAdjacentButEmpty = this.isAdjacentButEmtpy(this.selectedJewel, x, y);
        
        if (!clickedJewel || this.isSwapping) {
            return;
        }
        
        // If no jewel is currently selected
        if (!this.selectedJewel) {
            this.selectJewel(clickedJewel);
            return;
        }
        
        // If clicking on the already selected jewel, deselect it
        if (clickedJewel === this.selectedJewel) {
            this.deselectJewel();
            return;
        }
        
        // Check if clicked jewel is adjacent to selected jewel
        const isAdjacent = this.isAdjacent(this.selectedJewel, clickedJewel);
        
        if (isAdjacent) {
            // Mark for swap
            this.selectJewelForSwap(clickedJewel);
        } else {
            // Deselect current and select new jewel
            this.deselectJewel();
            this.selectJewel(clickedJewel);
        }
    }
    
    // Helper function to get jewel at world position
    getJewelAtWorldPosition(x, y) {
        let closestJewel = null;
        let minDistance = Infinity;
        
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                const distance = Phaser.Math.Distance.Between(jewel.x, jewel.y, x, y);
                if (distance < minDistance && distance < 50) { // 50 is half of jewel width/height
                    minDistance = distance;
                    closestJewel = jewel;
                }
            }
        });
        
        return closestJewel;
    }
    
    // Helper function to check if two jewels are adjacent (horizontally or vertically)
    isAdjacent(jewel1, jewel2) {
        const col1 = Math.floor((jewel1.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
        const row1 = Math.floor(jewel1.y / this.gridConfig.jewelHeight);
        
        const col2 = Math.floor((jewel2.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
        const row2 = Math.floor(jewel2.y / this.gridConfig.jewelHeight);
        
        // Check if jewels are adjacent (same row and adjacent columns, or same column and adjacent rows)
        return (row1 === row2 && Math.abs(col1 - col2) === 1) || (col1 === col2 && Math.abs(row1 - row2) === 1);
    }
    
    // Helper function to select a jewel for swap
    selectJewelForSwap(jewel) {
        this.swapWithJewel = jewel;
        this.tweens.add({
            targets: this.selectedJewel,
            scale: 1,
            duration: 200
        });
        this.swapJewel();
    }

    // Helper function to select a jewel for swap
    selectJewel(jewel) {
        this.selectedJewel = jewel;
        this.tweens.add({
            targets: jewel,
            scale: 1.2,
            duration: 200
        });
    }
    
    // Helper function to deselect a jewel
    deselectJewel() {
        if (this.selectedJewel) {
            this.tweens.add({
                targets: this.selectedJewel,
                scale: 1,
                duration: 200
            });
            this.selectedJewel = null;
        }
    }

    // Modified swap function to disable clicks during execution
    swapJewel() {
        if (this.isMovingUp === true) {
            this.time.delayedCall(500, ()=> {
                this.swapJewel();
            })
            return;
        }
        // Set swapping flag to prevent new clicks from being processed
        this.isSwapping = true;
        this.sound.play('switch');
        
        // Disable all jewel interactivity temporarily 
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                jewel.disableInteractive();
            }
        });
        
        // Perform the swap animation here - currently empty
        const fromX = this.selectedJewel.x;
        const fromY = this.selectedJewel.y;
        const toX = this.swapWithJewel.x;
        const toY = this.swapWithJewel.y;
        this.tweens.add({
            targets: this.selectedJewel,
            x: toX,
            y: toY,
            duration: 300
        });
        this.tweens.add({
            targets: this.swapWithJewel,
            x: fromX,
            y: fromY,
            duration: 300,
            onComplete: () => {
                this.checkMatches();
            }
        });
        this.selectedJewel = null;
        this.swapWithJewel = null;
        

        // After swap completes, re-enable interactivity and reset flag
        this.time.delayedCall(300, () => { // Adjust delay as needed for animation duration
            this.jewels.children.iterate((jewel) => {
                if (jewel) {
                    jewel.setInteractive();
                }
            });
            
            this.isSwapping = false;
        });
    }

    reduceMatches(amount) {
        this.matchesNeeded -= amount;
        if (this.matchesNeeded <= 0) {
            this.levelUp();
        }
        this.matchesText.setText(`Matches Needed: ${this.matchesNeeded}`);
    }

    // Function to check for matches and destroy them
    checkMatches() {
        this.checkWarning();
        const matchedJewels = new Set();
        
        // Check horizontal matches
        for (let row = 1; row <= this.gridConfig.rows; row++) {
            let count = 1;
            let currentType = this.getJewelAtPosition(1, row);
            
            for (let col = 2; col <= this.gridConfig.cols; col++) {
                const jewelType = this.getJewelAtPosition(col, row);
                
                if (jewelType === currentType && jewelType !== null) {
                    count++;
                } else {
                    if (count >= 3) {
                        this.reduceMatches(1);
                        // Add all jewels in this match to the matched set
                        for (let i = col - count; i < col; i++) {
                            const key = `${i},${row}`;
                            matchedJewels.add(key);
                        }
                    }
                    count = 1;
                    currentType = jewelType;
                }
            }
            
            // Check for match at the end of row
            if (count >= 3) {
                this.reduceMatches(1);
                for (let i = this.gridConfig.cols - count + 1; i <= this.gridConfig.cols; i++) {
                    const key = `${i},${row}`;
                    matchedJewels.add(key);
                }
            }
        }
        
        // Check vertical matches
        for (let col = 1; col <= this.gridConfig.cols; col++) {
            let count = 1;
            let currentType = this.getJewelAtPosition(col, 0);
            
            for (let row = 1; row <= this.gridConfig.rows; row++) {
                const jewelType = this.getJewelAtPosition(col, row);
                
                if (jewelType === currentType && jewelType !== null) {
                    count++;
                } else {
                    if (count >= 3) {
                        this.reduceMatches(1);
                        // Add all jewels in this match to the matched set
                        for (let i = row - count; i < row; i++) {
                            const key = `${col},${i}`;
                            matchedJewels.add(key);
                        }
                    }
                    count = 1;
                    currentType = jewelType;
                }
            }
            
            // Check for match at the end of column
            if (count >= 3) {
                this.reduceMatches(1);
                for (let i = this.gridConfig.rows - count + 1; i <= this.gridConfig.rows; i++) {
                    const key = `${col},${i}`;
                    matchedJewels.add(key);
                }
            }
        }
        
        // If we found matches, destroy them and play video
        if (matchedJewels.size > 0) {
            this.playVideo(matchedJewels.size);
            this.playAudio(matchedJewels.size);
            const scoreMatches = matchedJewels.size / 3;
            const scoreAdd = Math.ceil(scoreMatches ** 2) * 10;
            this.score += scoreAdd;
            this.scoreText.setText(`Score: ${this.score}`);
            // ADD SCORE
            this.destroyMatchedJewels(matchedJewels);
            return true;
        }
        
        return false;
    }

    playVideo(amount) {
        if (this.isPlayingVideo === true) {
            return;
        }

        this.isPlayingVideo = true;
        let video = null;
        
        if (amount >= 5) {
            video = `${this.ally}-excited`;
        } else if (amount >= 4) {
            video = `${this.ally}-pleased`;
        } else {
            video = `${this.ally}-match`;
        }
        const showVideo = this.add.video(350, 610, video).setOrigin(0.5).setDepth(100);
        showVideo.play(false);
        this.time.delayedCall(5000, () => {
            this.isPlayingVideo = false;
            showVideo.destroy();
        });
    }

    playAudio(amount) {
        if (this.isPlayingAudio === true) {
            return;
        }

        this.isPlayingAudio = true;
        let audio = null;
        
        if (amount >= 5) {
            audio = `${this.ally}-c`;
        } else if (amount >= 4) {
            audio = `${this.ally}-b`;
        } else {
            const rand = Phaser.Math.Between(1, 3);
            audio = `${this.ally}-a${rand}`;
        }
        this.sound.play(audio);
        this.time.delayedCall(2000, () => {
            this.isPlayingAudio = false;
        });
    }

    // Function to destroy matched jewels
    destroyMatchedJewels(matchedJewels) {
        if (this.isDestroying) {
            return;
        }

        this.isDestroying = true;
        // Create an array of jewels to destroy
        const jewelsToDestroy = [];
        
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
                const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
                const key = `${col},${row}`;
                
                if (matchedJewels.has(key)) {
                    jewelsToDestroy.push(jewel);
                }
            }
        });
        
        this.sound.play('clear');

        // Animate destruction
        jewelsToDestroy.forEach((jewel) => {
            this.tweens.add({
                targets: jewel,
                scaleX: 0,
                scaleY: 0,
                alpha: 0,
                duration: 200,
                onComplete: () => {
                    jewel.destroy();
                    this.time.delayedCall(100, () => {
                        this.isDestroying = false;
                        this.dropJewels();
                    });                    
                }
            });
        });
    }

    dropJewels() {
        if (this.isDropping) {
            return;
        }

        this.isDropping = true;
        
        // Create a grid representation to track jewel positions
        const grid = [];
        for (let row = 1; row <= this.gridConfig.rows; row++) {
            grid[row] = [];
            for (let col = 1; col <= this.gridConfig.cols; col++) {
                grid[row][col] = null;
            }
        }
        
        // Populate the grid with jewel positions
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
                const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
                
                // Ensure we're within grid bounds
                if (col >= 1 && col <= this.gridConfig.cols && row >= 1 && row <= this.gridConfig.rows) {
                    grid[row][col] = jewel;
                }
            }
        });
        
        // Find jewels that need to drop and their target positions
        const jewelsToDrop = [];
        
        for (let col = 1; col <= this.gridConfig.cols; col++) {
            let emptySpaces = 0;
            
            // Process from bottom to top
            for (let row = this.gridConfig.rows; row >= 1; row--) {
                if (grid[row][col] === null) {
                    emptySpaces++;
                } else if (emptySpaces > 0) {
                    // This jewel needs to drop
                    const jewel = grid[row][col];
                    const targetRow = row + emptySpaces;
                    
                    jewelsToDrop.push({
                        jewel: jewel,
                        fromRow: row,
                        toRow: targetRow
                    });
                    
                    // Update grid reference
                    grid[row][col] = null;
                    grid[targetRow][col] = jewel;
                }
            }
        }
        
        // If no jewels need to drop, we're done
        if (jewelsToDrop.length === 0) {
            this.isDropping = false;
            return;
        }
        
        // Animate the dropping
        let droppedCount = 0;
        
        jewelsToDrop.forEach((dropInfo) => {
            const { jewel, fromRow, toRow } = dropInfo;
            
            // Calculate target y position
            const targetY = toRow * this.gridConfig.jewelHeight;
            
            // Animate the jewel dropping
            this.tweens.add({
                targets: jewel,
                y: targetY,
                duration: 300,
                ease: 'Linear',
                onComplete: () => {
                    droppedCount++;
                    
                    // When all jewels have dropped, check for new matches
                    if (droppedCount === jewelsToDrop.length) {
                        this.time.delayedCall(400, () => {
                            this.isDropping = false;
                            // Check for new matches after dropping
                            this.checkMatches();
                        });
                    }
                }
            });
        });
    }

    // Function to move all jewels up one row
    moveAllJewelsUp() {
        this.isMovingUp = true;
        // Check if any jewel is at row 1 (topmost) that would go to row 0
        let gameOver = false;
        
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
                const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
                
                // If jewel is at row 1 and would move up to row 0, game over
                if (row === 1 && col >= 1 && col <= this.gridConfig.cols) {
                    gameOver = true;
                }
            }
        });
        
        // If game over, end the game
        if (gameOver) {
            this.gameOver();
            return;
        }
        
        // Move all jewels up one row
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
                const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
                
                // Only move jewels that are not at the top row
                if (row > 1 && col >= 1 && col <= this.gridConfig.cols) {
                    const targetRow = row - 1;
                    const targetY = targetRow * this.gridConfig.jewelHeight;
                    
                    // Animate the jewel moving up
                    this.tweens.add({
                        targets: jewel,
                        y: targetY,
                        duration: 300,
                        ease: 'Linear'
                    });
                }
            }
        });
        
        // Create new bottom row after moving all jewels up
        this.time.delayedCall(300, () => {
            this.isMovingUp = false;
            this.createBottomRow();
            this.checkWarning();
        });
    }

    // Function to create a new row of jewels at the bottom
    createBottomRow() {
        const newRow = 8;
        let jewelDelay = 0;
        
        for (let col = 1; col <= this.gridConfig.cols; col++) {
            let type = null;
            let match = false;

            do {
                type = Phaser.Math.Between(0, this.numberOfJewels - 1);
                match = false;

                // Check horizontal matches in the new row
                if (col >= 3) {
                    // Check if this would create a horizontal match of 3 or more
                    const leftType = this.getJewelAtPosition(col-1, newRow);
                    const leftLeftType = this.getJewelAtPosition(col-2, newRow);
                    
                    if (leftType === type && leftLeftType === type) {
                        match = true;
                    }
                }

                // Check vertical matches in the columns above
                if (newRow <= this.gridConfig.rows) {
                    const aboveType = this.getJewelAtPosition(col, newRow - 1);
                    
                    if (aboveType === type) {
                        // Check if there's a match of 3 or more by looking at additional positions
                        let count = 1;
                        
                        // Look up to see how many matching jewels we have in the column
                        for (let row = newRow - 2; row < this.gridConfig.rows; row++) {
                            const jewelType = this.getJewelAtPosition(col, row);
                            if (jewelType === type) {
                                count++;
                            } else {
                                break;
                            }
                        }
                        
                        // If we have 3 or more in a vertical line, it's a match
                        if (count >= 3) {
                            match = true;
                        }
                    }
                }

                // Also check for matches with jewels above the new row (if they exist)
                if (newRow < this.gridConfig.rows && col <= this.gridConfig.cols) {
                    const jewelAbove = this.getJewelAtPosition(col, newRow - 1);
                    
                    if (jewelAbove !== null) {
                        // Check horizontal match with jewels in the same row
                        let count = 0;
                        
                        // Look left to see how many matching jewels we have in that row
                        for (let c = col - 1; c >= 1; c--) {
                            const jewelType = this.getJewelAtPosition(c, newRow);
                            if (jewelType === type) {
                                count++;
                            } else {
                                break;
                            }
                        }
                        
                        // Look right to see how many matching jewels we have in that row
                        for (let c = col + 1; c <= this.gridConfig.cols; c++) {
                            const jewelType = this.getJewelAtPosition(c, newRow);
                            if (jewelType === type) {
                                count++;
                            } else {
                                break;
                            }
                        }
                        
                        // If we have at least 2 matching jewels in the row and one more above,
                        // or any other match scenario that creates a 3-in-a-row
                        if (count >= 2 && jewelAbove === type) {
                            match = true;
                        }
                    }
                }

            } while (match === true);
            
            // Create the jewel at the correct position
            this.createJewel(type, col, newRow);
        }
    }

    refreshJewelSprites() {
        // Iterate through all jewels and update their sprite frames
        this.jewels.children.iterate((jewel) => {
            if (jewel && jewel.jewelType !== undefined) {
                // Update the jewel's frame to reflect the new spritePlus value
                jewel.setFrame(jewel.jewelType + this.spritePlus);
            }
        });
    }

    refreshScene(originalAlly) {
        // Stop the current music
        this.bgMusic.stop();
        
        // Play the new ally's music
        this.bgMusic = this.sound.add(`${this.ally}-music`, { volume: 0.2 });
        this.bgMusic.loop = true;
        this.bgMusic.play();

        this.time.delayedCall(4000, () => {
            this.sound.play(`${this.ally}-intro`);
        });

        // Refresh the ally video with the new ally
        if (this.allyVideo) {
            console.log('update-vid ',this.ally);
            // Destroy the existing video
            this.allyVideo.destroy();
            
            // Create a new video with the updated ally
            this.allyVideo = this.add.video(350, 610, `${this.ally}-resting`).setOrigin(0.5);
            this.allyVideo.play(true);
            this.allyVideo.postFX.addGlow();
        }

        // Refresh the background video with the new ally
        if (this.bgVideo) {
            // Destroy the existing background video
            this.bgVideo.destroy();
            
            // Create a new background video with the updated ally
            this.bgVideo = this.add.video(0, 0, `${this.ally}-background`).setOrigin(0);
            this.bgVideo.scaleX = this.scale.width / 848;
            this.bgVideo.scaleY = this.scale.height / 480;
            this.bgVideo.play(true).setDepth(-1);
        }
    }

    checkWarning() {
        // Check if there are any jewels in row 1 (topmost row)
        let hasJewelsInRow1 = false;
        
        this.time.delayedCall(500, () => {
            this.jewels.children.iterate((jewel) => {
                if (jewel) {
                    const col = Math.floor((jewel.x - this.gridConfig.leftPadding) / this.gridConfig.jewelWidth);
                    const row = Math.floor(jewel.y / this.gridConfig.jewelHeight);
                    
                    // If jewel is in row 1, set the flag to true
                    if (row === 1 && col >= 1 && col <= this.gridConfig.cols) {
                        hasJewelsInRow1 = true;
                        return false; // Stop iteration once we find one
                    }
                }
            });
            
            if (this.rowOne === true && hasJewelsInRow1 === false) {
                this.rowOne = false;
                this.grid.setFillStyle(this.gridColor).setAlpha(0.5);
                this.alarm.stop();
                this.alarmFlash.remove();
                this.alarmFlash = null;
            } else if (this.rowOne === false && hasJewelsInRow1) {
                console.log('in row one');
                this.rowOne = true;
                this.alarm = this.sound.add('alarm', { loop: true, volume: 1 });
                this.alarm.play();
                this.alarmFlash = this.tweens.add({
                    targets: this.grid,
                    fillColor: 0xFF0000,
                    duration: 3000,
                    alpha: .7,
                    ease: 'Linear',
                    yoyo: true,
                    repeat: -1
                });
            }
        });
    }

    levelUp() {
        this.level ++;
        const newLevel = LEVEL_CONFIG[this.level];
        this.numberOfJewels = newLevel.numberOfJewels;
        this.matchesNeeded = newLevel.matchesNeeded;
        this.moveInterval = newLevel.moveInterval;
        this.gridColor = newLevel.gridColor;
        this.LevelText.setText(`Level: ${this.level}`);
        this.sound.play('level-up');
        this.sound.play('level-complete');

        this.grid.setFillStyle(newLevel.gridColor).setAlpha(0.5);

        if (this.ally !== newLevel.ally) {
            this.sound.play(`${this.ally}-outro`);
            this.time.delayedCall(1000, () => {
                const originalAlly = this.ally;
                this.ally = newLevel.ally;
                this.refreshScene(originalAlly);
                this.spritePlus = newLevel.spritePlus;
                this.refreshJewelSprites();
            });
        }

        // Create the New Level text
        const newLevelText = this.add.text(1150, 250, `Level ${this.level}`, {
            fontFamily: 'code, arial',
            fontSize: '100px',
            fill: '#ea00ffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0.5);

        // Add cool eye-catching effect
        this.tweens.add({
            targets: newLevelText,
            scale: { from: 0.5, to: 1.5 },
            alpha: { from: 0, to: 1 },
            duration: 1000,
            ease: 'Back.easeOut',
            yoyo: true
        });

        // Fade out and destroy after 500ms
        this.time.delayedCall(1200, () => {
            this.tweens.add({
                targets: newLevelText,
                angle: 360,
                scale: 0,
                alpha: 0,
                duration: 500,
                onComplete: () => {
                    newLevelText.destroy();
                }
            });
        });
    }

    // Game over function
    gameOver() {
        console.log('Game Over!');
        this.gameStatus = false;
        this.sound.play('game-over');
        this.rowOne = false;
        this.grid.setFillStyle(this.gridColor).setAlpha(0.5);
        this.alarm.stop();
        this.alarmFlash.remove();
        this.alarmFlash = null;
        
        // Make all jewels bounce off screen
        this.jewels.children.iterate((jewel) => {
            if (jewel) {
                // Enable physics for the jewel if not already enabled
                if (!jewel.body) {
                    this.physics.add.existing(jewel);
                }

                // Remove world bounds collision
                jewel.body.setCollideWorldBounds(false);
                
                // Set random velocity for bouncing effect
                const angle = Phaser.Math.Between(0, 360);
                const speed = Phaser.Math.Between(100, 300);
                
                jewel.body.setVelocity(
                    Math.cos(angle) * speed,
                    Math.sin(angle) * speed
                );
                
                // Add some rotation for visual effect
                jewel.body.angularVelocity = Phaser.Math.Between(-200, 200);
            }
        });

        // Create the New Level text
        const gameOverText = this.add.text(1150, 250, `Game Over`, {
            fontFamily: 'code, arial',
            fontSize: '100px',
            fill: '#ea00ffff',
            padding: {
                left: 10,
                right: 10,
                top: 5,
                bottom: 5
            }
        }).setOrigin(0.5);

        // Add cool eye-catching effect
        this.tweens.add({
            targets: gameOverText,
            scale: { from: 0.5, to: 1.5 },
            alpha: { from: 0, to: 1 },
            duration: 1000,
            ease: 'Back.easeOut',
        });

        // Fade out and destroy after 2000ms
        this.time.delayedCall(10200, () => {
            this.tweens.add({
                targets: gameOverText,
                angle: 360,
                scale: 0,
                alpha: 0,
                duration: 500,
                onComplete: () => {
                    gameOverText.destroy();
                    this.time.delayedCall(3000, () => {
                        // Fade out camera
                        this.tweens.add({
                            targets: this.cameras.main,
                            opacity: 0,
                            duration: 1500,
                            ease: 'Linear',
                            onComplete: () => {
                                this.scene.restart();
                            }
                        });
                    });
                }
            });
        });
    }
}