/**
This activity uses arrays and loops to store and spawn tile objects. Swap algorithms are used to help program the logic. The player must click the tiles to complete a traditional slide puzzle.
 */

//******************Scene Object - Initialize When Scene Starts Event****************//
// this function takes an array
// shuffles it randomly and returns it
$this.shuffle = function(arr){
    arr.sort(() => random(1, -1));
    return arr;
};

// set up the scene
if ($this.scene.state() == "PLAY") {
    // store the solution as ordered array of tile numbers
    $this.solution = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0];
    // use the shuffle function to randomize the puzzle tiles
    $this.puzzleTiles = $this.shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]);
    
    // set up loop helper variables to place the tiles
    var xOffset = 200;
    var yOffset = 100;
    var tileSpacing = 100;
    // keep track of where we are in the puzzle array
    var tileIndex = 0;
    
    // loop through the grid row by row to place 16 tiles
    for (var row = 0; row < 4; row++) {
        for (var col=0; col < 4; col++) {
            // find the current tile number
            // based on the shuffled puzzle array
            var currentTileNumber = $this.puzzleTiles[tileIndex];
            // find the tile object
            var tile = $this.findName("tile" + currentTileNumber);
            // assign the tile its number for easy use
            tile.number = currentTileNumber;
            // make the tile see-through
            tile.opacity(0.5);
            // place the tilein the correct spot in the grid
            tile.x(col * tileSpacing + xOffset);
            tile.y(row * tileSpacing + yOffset);
            // increment to the next tile
            tileIndex++;
        }
    }
    // after all the tiles have placed, check the solution
    $this.checkSolution();
}

// this function runs when the player clicks on a tile
$this.checkMove = function(clickedTile) {
    // see how far away the clicked tile is from the blank tile
    // use the absolute value function to always get a positive number
    var xDistance = Math.abs(clickedTile.x() - tile0.x());
    var yDistance = Math.abs(clickedTile.y() - tile0.y());
    
    // if the clicked tile is only 1 tile away
    if ((xDistance === 100 && yDistance === 0) || 
        (xDistance === 0 && yDistance === 100 )) {
            // swap the two tiles using temporary variables
            // first store the location of the clicked tile
            var originalClickedTileX = clickedTile.x();
            var originalClickedTileY = clickedTile.y();
            // move the clicked tile to the blank tile's location
            clickedTile.x(tile0.x());
            clickedTile.y(tile0.y());
            // move the blank tile to the saved clicked tile location
            tile0.x(originalClickedTileX);
            tile0.y(originalClickedTileY);
            
            // swap the tiles in the puzzle array 
            // find the original index of the clicked tile in the puzzleTiles array
            var originalClickedTileIndex = $this.puzzleTiles.indexOf(clickedTile.number);
            // find the original index of the blank tile in the puzzleTiles array
            var originalBlankIndex = $this.puzzleTiles.indexOf(0);
            // swap the blank tile and the clickedtile in the puzzle array
            $this.puzzleTiles[originalClickedTileIndex] = 0;
            $this.puzzleTiles[originalBlankIndex] = clickedTile.number;
            // after every swap, check for a solution
            $this.checkSolution();
        }
};

// this function runs aftrer every tile swap
$this.checkSolution = function() {
    // store the number of correct tiles
    var correctTiles = 0;
    // loop through each tile in puzzle array
    for (var i = 0; i < 16; i++) {
        // find the tile
        var tile = $this.findName ("tile" + $this.puzzleTiles[i]);
        // compare the current tile with the correct tile
        if (tile.number === $this.solution[i]) {
            // if the tile is correct, make it completely visible
            tile.opacity(1);
            // increment the correctTiles variable
            correctTiles++;
        } else {
            // if the tile is incorrect, make it see- through
            tile.opacity(0.5);
        }
    }
    // update the message to the player
    message.text("Correct Tiles: " + correctTiles);
};

//************************all tiles - Mouse Click Event***************************//
$this.scene.checkMove($this);