/**** 
* Classes
****/
var TetrominoBlock = Container.expand(function (type, i, j, blockSize) {
  var self = Container.call(this);
  var blockGraphic = self.createAsset('tetromino_' + type, type + ' Tetromino block', 0.5, 0.5);
  self.x = j * blockSize;
  self.y = i * blockSize;
});
// Define Tetromino class
var Tetromino = Container.expand(function () {
  var self = Container.call(this);
  Tetromino.prototype.checkCollision = function (dx, dy, board) {
    for (var i = 0; i < this.blocks.length; i++) {
      var block = this.blocks[i];
      var newX = this.x + block.x + dx;
      var newY = this.y + block.y + dy;
      var gridX = Math.floor(newX / blockSize);
      var gridY = Math.floor(newY / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY >= boardHeight) {
        return true; // Collision with board boundaries
      }
      if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        return true; // Collision with another block
      }
    }
    return false;
  };
  this.blocks = [];
  this.type = '';
  this.rotationIndex = 0;
  this.initializeBlocks = function (layout) {
    this.initializeBlocks = function (layout, blockSize) {
      for (var i = 0; i < layout.length; i++) {
        for (var j = 0; j < layout[i].length; j++) {
          if (layout[i][j]) {
            var block = new TetrominoBlock(this.type, i, j, blockSize);
            this.blocks.push(block);
            this.addChild(block);
          }
        }
      }
    };
  };
  this.create = function (type, blockSize) {
    this.type = type;
    this.rotationIndex = 0;
    var layout = tetrominoLayouts[type][this.rotationIndex];
    this.initializeBlocks(layout, blockSize);
  };
  this.rotate = function () {
    var oldRotationIndex = this.rotationIndex;
    var newRotationIndex = (this.rotationIndex + 1) % tetrominoLayouts[this.type].length;
    this.rotationIndex = newRotationIndex;
    this.updateBlockPositions();
    if (this.checkCollision(0, 0, board)) {
      this.rotationIndex = oldRotationIndex;
      this.updateBlockPositions();
    }
  };
  this.updateBlockPositions = function () {
    var layout = tetrominoLayouts[this.type][this.rotationIndex];
    var k = 0;
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          this.blocks[k].x = j * this.blocks[k].width;
          this.blocks[k].y = i * this.blocks[k].height;
          k++;
        }
      }
    }
  };
  this.move = function (dx, dy) {
    if (!this.checkCollision(dx, dy, board)) {
      this.x += dx;
      this.y += dy;
    } else if (dy > 0) {
      board.fixTetromino(this);
      spawnTetromino();
    }
  };
});
// Define GameBoard class
var GameBoard = Container.expand(function () {
  var self = Container.call(this);
  this.grid = [];
  this.init = function () {
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.fixTetromino = function (tetromino) {
    var blocks = tetromino.blocks;
    for (var i = 0; i < blocks.length; i++) {
      var block = blocks[i];
      var x = Math.round((block.x + tetromino.x - this.x) / blockSize);
      var y = Math.round((block.y + tetromino.y - this.y) / blockSize);
      if (y < boardHeight && x < boardWidth) {
        this.grid[y][x] = block;
        block.x = x * blockSize;
        block.y = y * blockSize;
        this.addChild(block);
      } else if (y < 0) {
        LK.showGameOver();
        return false;
      }
    }
    this.checkLines();
    return true;
  };
  this.isGameOver = function () {
    for (var x = 0; x < boardWidth; x++) {
      if (this.grid[0][x] !== null) {
        return true;
      }
    }
    return false;
  };
  this.checkLines = function () {
    for (var y = 0; y < boardHeight; y++) {
      var lineComplete = true;
      for (var x = 0; x < boardWidth; x++) {
        if (this.grid[y][x] === null) {
          lineComplete = false;
          break;
        }
      }
      if (lineComplete) {
        for (var row = y; row > 0; row--) {
          for (var x = 0; x < boardWidth; x++) {
            this.grid[row][x] = this.grid[row - 1][x];
            if (this.grid[row][x]) {
              this.grid[row][x].y += blockSize;
            }
          }
        }
        for (var x = 0; x < boardWidth; x++) {
          this.grid[0][x] = null;
        }
        for (var x = 0; x < boardWidth; x++) {
          if (this.grid[y][x]) {
            this.grid[y][x].destroy();
            this.grid[y][x] = null;
          }
        }
        var linesCleared = 0;
        for (var y = 0; y < boardHeight; y++) {
          var lineComplete = true;
          for (var x = 0; x < boardWidth; x++) {
            if (this.grid[y][x] === null) {
              lineComplete = false;
              break;
            }
          }
          if (lineComplete) {
            linesCleared++;
            for (var row = y; row > 0; row--) {
              for (var x = 0; x < boardWidth; x++) {
                this.grid[row][x] = this.grid[row - 1][x];
                if (this.grid[row][x]) {
                  this.grid[row][x].y += blockSize;
                }
              }
            }
            for (var x = 0; x < boardWidth; x++) {
              this.grid[0][x] = null;
            }
            for (var x = 0; x < boardWidth; x++) {
              if (this.grid[y][x]) {
                this.grid[y][x].destroy();
                this.grid[y][x] = null;
              }
            }
          }
        }
        if (linesCleared > 0) {
          var scoreToAdd = linesCleared === 1 ? 100 : linesCleared === 2 ? 300 : linesCleared === 3 ? 500 : 800;
          LK.setScore(LK.getScore() + scoreToAdd);
          gameUI.updateScore(LK.getScore());
        }
      }
    }
  };
  this.init();
});
// Define LowerField class for collecting Tetrominoes
var LowerField = Container.expand(function () {
  var self = Container.call(this);
  this.init = function () {
    this.grid = [];
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.init();
  this.addBlock = function (block, x, y) {
    if (y < boardHeight && x < boardWidth) {
      this.grid[y][x] = block;
      block.x = x * blockSize;
      block.y = y * blockSize;
      this.addChild(block);
    }
  };
});
// Define GameMenu class
var GameMenu = Container.expand(function () {
  var self = Container.call(this);
  this.startButton = new Text2('Start', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.startButton.on('down', function () {
    GameState.initialize();
    self.visible = false;
  });
  this.pauseButton = new Text2('Pause', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.pauseButton.on('down', function () {
    GameState.state = 'paused';
  });
  this.resumeButton = new Text2('Resume', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.resumeButton.on('down', function () {
    GameState.state = 'active';
  });
  this.restartButton = new Text2('Restart', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.restartButton.on('down', function () {
    GameState.initialize();
  });
  LK.gui.bottom.addChild(this.startButton);
  LK.gui.bottom.addChild(this.pauseButton);
  LK.gui.bottom.addChild(this.resumeButton);
  LK.gui.bottom.addChild(this.restartButton);
  this.pauseButton.visible = false;
  this.resumeButton.visible = false;
  this.restartButton.visible = false;
});
// Create a new GameMenu instance
// Create score display
var ScoreDisplay = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.linesText = new Text2('Lines: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.top.addChild(this.linesText);
  this.levelText.y = this.scoreText.height;
  this.linesText.y = this.scoreText.height * 2;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateLinesCleared = function (lines) {
    this.linesText.setText('Lines: ' + lines.toString());
  };
});
// Create a new ScoreDisplay instance
var GameUI = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.nextTetrominoPreview = new Container();
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.topRight.addChild(this.nextTetrominoPreview);
  this.scoreText.y = 20;
  this.levelText.y = this.scoreText.height + 20;
  this.nextTetrominoPreview.y = 20;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateNextTetrominoPreview = function (type) {
    this.nextTetrominoPreview.removeChildren();
    var layout = GameState.tetrominoLayouts[type][0];
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          var block = LK.getAsset('tetromino_' + type + '_preview', 'Next Tetromino block', 0.5, 0.5);
          block.x = j * (blockSize * 0.5);
          block.y = i * (blockSize * 0.5);
          this.nextTetrominoPreview.addChild(block);
        }
      }
    }
  };
});
/**** 
* Initialize Game
****/
// Create a new GameUI instance
var game = new LK.Game({
  backgroundColor: 0x000000 // Init game with black background for better contrast
});
/**** 
* Game Code
****/
// Create a new GameMenu instance
var gameMenu = new GameMenu();
// Define game constants and variables
var GameState = {
  boardWidth: 10,
  boardHeight: 20,
  blockSize: 2048 / 10,
  // Calculate block size based on viewable area width
  fallRate: 1000,
  // Time in milliseconds between each Tetromino fall step
  score: 0,
  // Initialize current score
  level: 1,
  // Initialize game level
  state: 'active',
  // Game state can be 'paused', 'active', or 'gameOver'
  grid: [],
  initializeGrid: function () {
    for (var i = 0; i < this.boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < this.boardWidth; j++) {
        this.grid[i][j] = null; // Each cell starts as null (empty)
      }
    }
  }
};
GameState.initializeGrid();
// Initialize the first Tetromino
spawnTetromino();
// Define game constants and variables
var TetrominoMovement = {
  calculateMove: function calculateMove(tetromino, dx, dy, board) {
    var newX = tetromino.x + dx;
    var newY = tetromino.y + dy;
    var canMove = true;
    for (var i = 0; i < tetromino.blocks.length; i++) {
      var block = tetromino.blocks[i];
      var gridX = Math.round((block.x + newX - board.x) / blockSize);
      var gridY = Math.round((block.y + newY - board.y) / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY < 0 || gridY >= boardHeight) {
        canMove = false;
        break;
      } else if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        canMove = false;
        break;
      }
    }
    return {
      canMove: canMove,
      newX: newX,
      newY: newY
    };
  }
};
var boardWidth = 10;
var boardHeight = 20;
var blockSize = 2048 / boardWidth; // Calculate block size based on viewable area width
var fallRate = 1000; // Time in milliseconds between each Tetromino fall step
// GameBoard class is now encapsulated and instantiated separately
var board = new GameBoard();
game.addChild(board);
var GameState = {
  currentTetromino: null,
  nextTetrominoType: null,
  tetrominoTypes: ['I', 'J', 'L', 'O', 'S', 'T', 'Z'],
  tetrominoLayouts: {
    'I': [[[1, 1, 1, 1]]],
    'J': [[[1, 0, 0], [1, 1, 1]]],
    'L': [[[0, 0, 1], [1, 1, 1]]],
    'O': [[[1, 1], [1, 1]]],
    'S': [[[0, 1, 1], [1, 1, 0]]],
    'T': [[[0, 1, 0], [1, 1, 1]]],
    'Z': [[[1, 1, 0], [0, 1, 1]]]
  },
  scoreTxt: null,
  isGameOver: false,
  initialize: function () {
    this.currentTetromino = null;
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.linesCleared = 0;
    this.score = 0;
    this.level = 1;
    this.state = 'active';
    this.spawnTetromino();
    gameUI.updateScore(this.score);
    gameUI.updateLevel(this.level);
    gameUI.updateLinesCleared(this.linesCleared);
    gameMenu.startButton.visible = false;
    gameMenu.pauseButton.visible = true;
    gameMenu.resumeButton.visible = false;
    gameMenu.restartButton.visible = true;
    board.init();
    game.addChild(board);
    board.x = (2048 - boardWidth * blockSize) / 2;
    board.y = (2732 - boardHeight * blockSize) / 2;
    game.addChild(gameUI);
  },
  spawnTetromino: function () {
    GameState.linesCleared = 0;
    gameUI.updateScore(GameState.score);
    gameUI.updateLevel(GameState.level);
    gameUI.updateNextTetrominoPreview(GameState.nextTetrominoType);
    var type = this.nextTetrominoType != null ? this.nextTetrominoType : this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.currentTetromino = new Tetromino();
    this.currentTetromino.create(type);
    this.currentTetromino.x = board.x + (boardWidth * blockSize - this.currentTetromino.width) / 2;
    this.currentTetromino.y = board.y - this.currentTetromino.height;
    game.addChild(this.currentTetromino);
  },
  gameOver: function () {
    this.isGameOver = true;
    LK.showGameOver();
  }
};
GameState.initialize();
// Initialize board
board.init();
// Center the board on the screen
board.x = (2048 - boardWidth * blockSize) / 2;
board.y = (2732 - boardHeight * blockSize) / 2;
// Create a new GameUI instance
var gameUI = new GameUI();
// Function to spawn a new tetromino
function spawnTetromino(blockSize) {
  var type = GameState.nextTetrominoType != null ? GameState.nextTetrominoType : GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.nextTetrominoType = GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.currentTetromino = new Tetromino();
  GameState.currentTetromino.create(type, blockSize);
  GameState.currentTetromino.x = board.x + boardWidth / 2 * blockSize - GameState.currentTetromino.width / 2;
  GameState.currentTetromino.y = board.y;
  game.addChild(GameState.currentTetromino);
}
// Start the game with a new tetromino
spawnTetromino();
// Implement automatic Tetromino descent
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    // Define touch areas for control
    var leftArea = {
      x: board.x,
      width: boardWidth * blockSize / 3
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize * 2 / 3,
      width: boardWidth * blockSize / 3
    };
    var rotateArea = {
      x: board.x + boardWidth * blockSize / 3,
      width: boardWidth * blockSize / 3
    };
    // Move tetromino left
    if (touchPos.x >= leftArea.x && touchPos.x < leftArea.x + leftArea.width) {
      currentTetromino.move(-blockSize, 0);
    }
    // Move tetromino right
    else if (touchPos.x >= rightArea.x && touchPos.x < rightArea.x + rightArea.width) {
      currentTetromino.move(blockSize, 0);
    }
    // Rotate tetromino
    else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width) {
      currentTetromino.rotate();
    }
  });
}
// Game loop
LK.on('tick', function () {
  if (GameState.state === 'paused') {
    return;
  }
  // Handle Tetromino descent
  if (GameState.currentTetromino && GameState.state === 'active') {
    if (LK.ticks % (fallRate / (1000 / 60)) === 0) {
      GameState.currentTetromino.move(0, blockSize);
    }
  }
  // Handle user input for moving and rotating the tetromino
  handleUserInput();
  // Check for completed lines
  board.checkLines();
  // Check for game over
  if (board.isGameOver()) {
    GameState.gameOver();
  }
});
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    var leftArea = {
      x: 0,
      width: board.x
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize,
      width: 2048 - (board.x + boardWidth * blockSize)
    };
    var rotateArea = {
      x: board.x,
      y: board.y,
      width: boardWidth * blockSize,
      height: boardHeight * blockSize
    };
    if (touchPos.x < leftArea.width) {
      GameState.currentTetromino.move(-blockSize, 0);
    } else if (touchPos.x > rightArea.x) {
      GameState.currentTetromino.move(blockSize, 0);
    } else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width && touchPos.y >= rotateArea.y && touchPos.y < rotateArea.y + rotateArea.height) {
      GameState.currentTetromino.rotate();
    }
  });
} /**** 
* Classes
****/
var TetrominoBlock = Container.expand(function (type, i, j, blockSize) {
  var self = Container.call(this);
  var blockGraphic = self.createAsset('tetromino_' + type, type + ' Tetromino block', 0.5, 0.5);
  self.x = j * blockSize;
  self.y = i * blockSize;
});
// Define Tetromino class
var Tetromino = Container.expand(function () {
  var self = Container.call(this);
  Tetromino.prototype.checkCollision = function (dx, dy, board) {
    for (var i = 0; i < this.blocks.length; i++) {
      var block = this.blocks[i];
      var newX = this.x + block.x + dx;
      var newY = this.y + block.y + dy;
      var gridX = Math.floor(newX / blockSize);
      var gridY = Math.floor(newY / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY >= boardHeight) {
        return true; // Collision with board boundaries
      }
      if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        return true; // Collision with another block
      }
    }
    return false;
  };
  this.blocks = [];
  this.type = '';
  this.rotationIndex = 0;
  this.initializeBlocks = function (layout) {
    this.initializeBlocks = function (layout, blockSize) {
      for (var i = 0; i < layout.length; i++) {
        for (var j = 0; j < layout[i].length; j++) {
          if (layout[i][j]) {
            var block = new TetrominoBlock(this.type, i, j, blockSize);
            this.blocks.push(block);
            this.addChild(block);
          }
        }
      }
    };
  };
  this.create = function (type, blockSize) {
    this.type = type;
    this.rotationIndex = 0;
    var layout = tetrominoLayouts[type][this.rotationIndex];
    this.initializeBlocks(layout, blockSize);
  };
  this.rotate = function () {
    var oldRotationIndex = this.rotationIndex;
    var newRotationIndex = (this.rotationIndex + 1) % tetrominoLayouts[this.type].length;
    this.rotationIndex = newRotationIndex;
    this.updateBlockPositions();
    if (this.checkCollision(0, 0, board)) {
      this.rotationIndex = oldRotationIndex;
      this.updateBlockPositions();
    }
  };
  this.updateBlockPositions = function () {
    var layout = tetrominoLayouts[this.type][this.rotationIndex];
    var k = 0;
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          this.blocks[k].x = j * this.blocks[k].width;
          this.blocks[k].y = i * this.blocks[k].height;
          k++;
        }
      }
    }
  };
  this.move = function (dx, dy) {
    if (!this.checkCollision(dx, dy, board)) {
      this.x += dx;
      this.y += dy;
    } else if (dy > 0) {
      board.fixTetromino(this);
      spawnTetromino();
    }
  };
});
// Define GameBoard class
var GameBoard = Container.expand(function () {
  var self = Container.call(this);
  this.grid = [];
  this.init = function () {
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.fixTetromino = function (tetromino) {
    var blocks = tetromino.blocks;
    for (var i = 0; i < blocks.length; i++) {
      var block = blocks[i];
      var x = Math.round((block.x + tetromino.x - this.x) / blockSize);
      var y = Math.round((block.y + tetromino.y - this.y) / blockSize);
      if (y < boardHeight && x < boardWidth) {
        this.grid[y][x] = block;
        block.x = x * blockSize;
        block.y = y * blockSize;
        this.addChild(block);
      } else if (y < 0) {
        LK.showGameOver();
        return false;
      }
    }
    this.checkLines();
    return true;
  };
  this.isGameOver = function () {
    for (var x = 0; x < boardWidth; x++) {
      if (this.grid[0][x] !== null) {
        return true;
      }
    }
    return false;
  };
  this.checkLines = function () {
    for (var y = 0; y < boardHeight; y++) {
      var lineComplete = true;
      for (var x = 0; x < boardWidth; x++) {
        if (this.grid[y][x] === null) {
          lineComplete = false;
          break;
        }
      }
      if (lineComplete) {
        for (var row = y; row > 0; row--) {
          for (var x = 0; x < boardWidth; x++) {
            this.grid[row][x] = this.grid[row - 1][x];
            if (this.grid[row][x]) {
              this.grid[row][x].y += blockSize;
            }
          }
        }
        for (var x = 0; x < boardWidth; x++) {
          this.grid[0][x] = null;
        }
        for (var x = 0; x < boardWidth; x++) {
          if (this.grid[y][x]) {
            this.grid[y][x].destroy();
            this.grid[y][x] = null;
          }
        }
        var linesCleared = 0;
        for (var y = 0; y < boardHeight; y++) {
          var lineComplete = true;
          for (var x = 0; x < boardWidth; x++) {
            if (this.grid[y][x] === null) {
              lineComplete = false;
              break;
            }
          }
          if (lineComplete) {
            linesCleared++;
            for (var row = y; row > 0; row--) {
              for (var x = 0; x < boardWidth; x++) {
                this.grid[row][x] = this.grid[row - 1][x];
                if (this.grid[row][x]) {
                  this.grid[row][x].y += blockSize;
                }
              }
            }
            for (var x = 0; x < boardWidth; x++) {
              this.grid[0][x] = null;
            }
            for (var x = 0; x < boardWidth; x++) {
              if (this.grid[y][x]) {
                this.grid[y][x].destroy();
                this.grid[y][x] = null;
              }
            }
          }
        }
        if (linesCleared > 0) {
          var scoreToAdd = linesCleared === 1 ? 100 : linesCleared === 2 ? 300 : linesCleared === 3 ? 500 : 800;
          LK.setScore(LK.getScore() + scoreToAdd);
          gameUI.updateScore(LK.getScore());
        }
      }
    }
  };
  this.init();
});
// Define LowerField class for collecting Tetrominoes
var LowerField = Container.expand(function () {
  var self = Container.call(this);
  this.init = function () {
    this.grid = [];
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.init();
  this.addBlock = function (block, x, y) {
    if (y < boardHeight && x < boardWidth) {
      this.grid[y][x] = block;
      block.x = x * blockSize;
      block.y = y * blockSize;
      this.addChild(block);
    }
  };
});
// Define GameMenu class
var GameMenu = Container.expand(function () {
  var self = Container.call(this);
  this.startButton = new Text2('Start', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.startButton.on('down', function () {
    GameState.initialize();
    self.visible = false;
  });
  this.pauseButton = new Text2('Pause', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.pauseButton.on('down', function () {
    GameState.state = 'paused';
  });
  this.resumeButton = new Text2('Resume', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.resumeButton.on('down', function () {
    GameState.state = 'active';
  });
  this.restartButton = new Text2('Restart', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.restartButton.on('down', function () {
    GameState.initialize();
  });
  LK.gui.bottom.addChild(this.startButton);
  LK.gui.bottom.addChild(this.pauseButton);
  LK.gui.bottom.addChild(this.resumeButton);
  LK.gui.bottom.addChild(this.restartButton);
  this.pauseButton.visible = false;
  this.resumeButton.visible = false;
  this.restartButton.visible = false;
});
// Create a new GameMenu instance
// Create score display
var ScoreDisplay = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.linesText = new Text2('Lines: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.top.addChild(this.linesText);
  this.levelText.y = this.scoreText.height;
  this.linesText.y = this.scoreText.height * 2;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateLinesCleared = function (lines) {
    this.linesText.setText('Lines: ' + lines.toString());
  };
});
// Create a new ScoreDisplay instance
var GameUI = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.nextTetrominoPreview = new Container();
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.topRight.addChild(this.nextTetrominoPreview);
  this.scoreText.y = 20;
  this.levelText.y = this.scoreText.height + 20;
  this.nextTetrominoPreview.y = 20;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateNextTetrominoPreview = function (type) {
    this.nextTetrominoPreview.removeChildren();
    var layout = GameState.tetrominoLayouts[type][0];
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          var block = LK.getAsset('tetromino_' + type + '_preview', 'Next Tetromino block', 0.5, 0.5);
          block.x = j * (blockSize * 0.5);
          block.y = i * (blockSize * 0.5);
          this.nextTetrominoPreview.addChild(block);
        }
      }
    }
  };
});
/**** 
* Initialize Game
****/
// Create a new GameUI instance
var game = new LK.Game({
  backgroundColor: 0x000000 // Init game with black background for better contrast
});
/**** 
* Game Code
****/
// Create a new GameMenu instance
var gameMenu = new GameMenu();
// Define game constants and variables
var GameState = {
  boardWidth: 10,
  boardHeight: 20,
  blockSize: 2048 / 10,
  // Calculate block size based on viewable area width
  fallRate: 1000,
  // Time in milliseconds between each Tetromino fall step
  score: 0,
  // Initialize current score
  level: 1,
  // Initialize game level
  state: 'active',
  // Game state can be 'paused', 'active', or 'gameOver'
  grid: [],
  initializeGrid: function () {
    for (var i = 0; i < this.boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < this.boardWidth; j++) {
        this.grid[i][j] = null; // Each cell starts as null (empty)
      }
    }
  }
};
GameState.initializeGrid();
// Initialize the first Tetromino
spawnTetromino();
// Define game constants and variables
var TetrominoMovement = {
  calculateMove: function calculateMove(tetromino, dx, dy, board) {
    var newX = tetromino.x + dx;
    var newY = tetromino.y + dy;
    var canMove = true;
    for (var i = 0; i < tetromino.blocks.length; i++) {
      var block = tetromino.blocks[i];
      var gridX = Math.round((block.x + newX - board.x) / blockSize);
      var gridY = Math.round((block.y + newY - board.y) / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY < 0 || gridY >= boardHeight) {
        canMove = false;
        break;
      } else if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        canMove = false;
        break;
      }
    }
    return {
      canMove: canMove,
      newX: newX,
      newY: newY
    };
  }
};
var boardWidth = 10;
var boardHeight = 20;
var blockSize = 2048 / boardWidth; // Calculate block size based on viewable area width
var fallRate = 1000; // Time in milliseconds between each Tetromino fall step
// GameBoard class is now encapsulated and instantiated separately
var board = new GameBoard();
game.addChild(board);
var GameState = {
  currentTetromino: null,
  nextTetrominoType: null,
  tetrominoTypes: ['I', 'J', 'L', 'O', 'S', 'T', 'Z'],
  tetrominoLayouts: {
    'I': [[[1, 1, 1, 1]]],
    'J': [[[1, 0, 0], [1, 1, 1]]],
    'L': [[[0, 0, 1], [1, 1, 1]]],
    'O': [[[1, 1], [1, 1]]],
    'S': [[[0, 1, 1], [1, 1, 0]]],
    'T': [[[0, 1, 0], [1, 1, 1]]],
    'Z': [[[1, 1, 0], [0, 1, 1]]]
  },
  scoreTxt: null,
  isGameOver: false,
  initialize: function () {
    this.currentTetromino = null;
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.linesCleared = 0;
    this.score = 0;
    this.level = 1;
    this.state = 'active';
    this.spawnTetromino();
    gameUI.updateScore(this.score);
    gameUI.updateLevel(this.level);
    gameUI.updateLinesCleared(this.linesCleared);
    gameMenu.startButton.visible = false;
    gameMenu.pauseButton.visible = true;
    gameMenu.resumeButton.visible = false;
    gameMenu.restartButton.visible = true;
    board.init();
    game.addChild(board);
    board.x = (2048 - boardWidth * blockSize) / 2;
    board.y = (2732 - boardHeight * blockSize) / 2;
    game.addChild(gameUI);
  },
  spawnTetromino: function () {
    GameState.linesCleared = 0;
    gameUI.updateScore(GameState.score);
    gameUI.updateLevel(GameState.level);
    gameUI.updateNextTetrominoPreview(GameState.nextTetrominoType);
    var type = this.nextTetrominoType != null ? this.nextTetrominoType : this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.currentTetromino = new Tetromino();
    this.currentTetromino.create(type);
    this.currentTetromino.x = board.x + (boardWidth * blockSize - this.currentTetromino.width) / 2;
    this.currentTetromino.y = board.y - this.currentTetromino.height;
    game.addChild(this.currentTetromino);
  },
  gameOver: function () {
    this.isGameOver = true;
    LK.showGameOver();
  }
};
GameState.initialize();
// Initialize board
board.init();
// Center the board on the screen
board.x = (2048 - boardWidth * blockSize) / 2;
board.y = (2732 - boardHeight * blockSize) / 2;
// Create a new GameUI instance
var gameUI = new GameUI();
// Function to spawn a new tetromino
function spawnTetromino(blockSize) {
  var type = GameState.nextTetrominoType != null ? GameState.nextTetrominoType : GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.nextTetrominoType = GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.currentTetromino = new Tetromino();
  GameState.currentTetromino.create(type, blockSize);
  GameState.currentTetromino.x = board.x + boardWidth / 2 * blockSize - GameState.currentTetromino.width / 2;
  GameState.currentTetromino.y = board.y;
  game.addChild(GameState.currentTetromino);
}
// Start the game with a new tetromino
spawnTetromino();
// Implement automatic Tetromino descent
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    // Define touch areas for control
    var leftArea = {
      x: board.x,
      width: boardWidth * blockSize / 3
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize * 2 / 3,
      width: boardWidth * blockSize / 3
    };
    var rotateArea = {
      x: board.x + boardWidth * blockSize / 3,
      width: boardWidth * blockSize / 3
    };
    // Move tetromino left
    if (touchPos.x >= leftArea.x && touchPos.x < leftArea.x + leftArea.width) {
      currentTetromino.move(-blockSize, 0);
    }
    // Move tetromino right
    else if (touchPos.x >= rightArea.x && touchPos.x < rightArea.x + rightArea.width) {
      currentTetromino.move(blockSize, 0);
    }
    // Rotate tetromino
    else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width) {
      currentTetromino.rotate();
    }
  });
}
// Game loop
LK.on('tick', function () {
  if (GameState.state === 'paused') {
    return;
  }
  // Handle Tetromino descent
  if (GameState.currentTetromino && GameState.state === 'active') {
    if (LK.ticks % (fallRate / (1000 / 60)) === 0) {
      GameState.currentTetromino.move(0, blockSize);
    }
  }
  // Handle user input for moving and rotating the tetromino
  handleUserInput();
  // Check for completed lines
  board.checkLines();
  // Check for game over
  if (board.isGameOver()) {
    GameState.gameOver();
  }
});
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    var leftArea = {
      x: 0,
      width: board.x
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize,
      width: 2048 - (board.x + boardWidth * blockSize)
    };
    var rotateArea = {
      x: board.x,
      y: board.y,
      width: boardWidth * blockSize,
      height: boardHeight * blockSize
    };
    if (touchPos.x < leftArea.width) {
      GameState.currentTetromino.move(-blockSize, 0);
    } else if (touchPos.x > rightArea.x) {
      GameState.currentTetromino.move(blockSize, 0);
    } else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width && touchPos.y >= rotateArea.y && touchPos.y < rotateArea.y + rotateArea.height) {
      GameState.currentTetromino.rotate();
    }
  });
}