-- NAME: Tic-Tac-Toe
-- DESC: Play vs AI opponent

-- Game states
local STATE_MENU = 0
local STATE_PLAYING = 1
local STATE_GAME_OVER = 2

-- Game constants
local GRID_SIZE = 3
local CELL_SIZE = 30
local CELL_SPACING = 2

function init()
    game.vars.state = STATE_MENU
    game.vars.grid = {}
    game.vars.player = 1  -- 1 = X, 2 = O
    game.vars.ai = 2
    game.vars.game_over = false
    game.vars.winner = 0  -- 0 = ongoing, 1 = player wins, 2 = ai wins, 3 = draw
    
    -- Enable continuous updates
    game.set_frame_updates(true)
    
    print("Tic-Tac-Toe initialized")
end

function update(event)
    local state = game.vars.state
    
    if state == STATE_MENU then
        if event.type == INPUT.TOUCH_DOWN or event.type == INPUT.BUTTON_0 or event.type == INPUT.BUTTON_1 then
            reset_game()
            game.vars.state = STATE_PLAYING
            return true
        end
    
    elseif state == STATE_PLAYING then
        if event.type == INPUT.TOUCH_DOWN then
            local cell = get_cell_at(event.x, event.y)
            if cell and game.vars.grid[cell] == 0 then
                -- Player move
                game.vars.grid[cell] = game.vars.player
                
                -- Check win
                local winner = check_winner()
                if winner ~= 0 then
                    if winner == game.vars.player then
                        game.vars.winner = 1
                    else
                        game.vars.winner = 2
                    end
                    game.vars.state = STATE_GAME_OVER
                    return true
                end
                
                -- Check draw
                if is_board_full() then
                    game.vars.winner = 3
                    game.vars.state = STATE_GAME_OVER
                    return true
                end
                
                -- AI move
                local ai_move = find_best_move()
                game.vars.grid[ai_move] = game.vars.ai
                
                -- Check win
                winner = check_winner()
                if winner ~= 0 then
                    if winner == game.vars.ai then
                        game.vars.winner = 2
                    end
                    game.vars.state = STATE_GAME_OVER
                    return true
                end
                
                -- Check draw
                if is_board_full() then
                    game.vars.winner = 3
                    game.vars.state = STATE_GAME_OVER
                    return true
                end
                
                return true
            end
        end
    
    elseif state == STATE_GAME_OVER then
        if event.type == INPUT.TOUCH_DOWN or event.type == INPUT.BUTTON_0 or event.type == INPUT.BUTTON_1 then
            game.vars.state = STATE_MENU
            return true
        end
    end
    
    return false
end

function draw()
    renderer.clear(false)
    
    local state = game.vars.state
    
    if state == STATE_MENU then
        renderer.text(game.width() / 2 - 50, game.height() / 2 - 30, "TIC-TAC-TOE", true)
        renderer.text(game.width() / 2 - 50, game.height() / 2, "Play vs AI", true)
        renderer.text(game.width() / 2 - 50, game.height() / 2 + 20, "Tap to Start", true)
    
    elseif state == STATE_PLAYING or state == STATE_GAME_OVER then
        -- Draw grid
        local start_x = (game.width() - (GRID_SIZE * (CELL_SIZE + CELL_SPACING))) / 2
        local start_y = 30
        
        for row = 0, GRID_SIZE - 1 do
            for col = 0, GRID_SIZE - 1 do
                local cell_idx = row * GRID_SIZE + col + 1
                local cell_x = start_x + col * (CELL_SIZE + CELL_SPACING)
                local cell_y = start_y + row * (CELL_SIZE + CELL_SPACING)
                
                -- Draw cell
                renderer.rect(cell_x, cell_y, CELL_SIZE, CELL_SIZE, true, false)
                
                -- Draw X or O
                local value = game.vars.grid[cell_idx]
                if value == 1 then
                    -- Draw X
                    renderer.line(cell_x + 2, cell_y + 2, cell_x + CELL_SIZE - 2, cell_y + CELL_SIZE - 2, true, 1)
                    renderer.line(cell_x + CELL_SIZE - 2, cell_y + 2, cell_x + 2, cell_y + CELL_SIZE - 2, true, 1)
                elseif value == 2 then
                    -- Draw O
                    renderer.circle(cell_x + CELL_SIZE / 2, cell_y + CELL_SIZE / 2, CELL_SIZE / 2 - 2, true, false)
                end
            end
        end
        
        if state == STATE_GAME_OVER then
            if game.vars.winner == 1 then
                renderer.text(game.width() / 2 - 30, 10, "YOU WIN!", true)
            elseif game.vars.winner == 2 then
                renderer.text(game.width() / 2 - 30, 10, "AI WINS!", true)
            else
                renderer.text(game.width() / 2 - 20, 10, "DRAW!", true)
            end
            
            renderer.text(game.width() / 2 - 60, game.height() - 15, "Tap to Menu", true)
        end
    end
end

function get_cell_at(x, y)
    local start_x = (game.width() - (GRID_SIZE * (CELL_SIZE + CELL_SPACING))) / 2
    local start_y = 30
    
    for row = 0, GRID_SIZE - 1 do
        for col = 0, GRID_SIZE - 1 do
            local cell_x = start_x + col * (CELL_SIZE + CELL_SPACING)
            local cell_y = start_y + row * (CELL_SIZE + CELL_SPACING)
            
            if x >= cell_x and x < cell_x + CELL_SIZE and
               y >= cell_y and y < cell_y + CELL_SIZE then
                return row * GRID_SIZE + col + 1
            end
        end
    end
    
    return nil
end

function check_winner()
    -- Check rows
    for row = 0, GRID_SIZE - 1 do
        local val = game.vars.grid[row * GRID_SIZE + 1]
        if val ~= 0 then
            local match = true
            for col = 1, GRID_SIZE - 1 do
                if game.vars.grid[row * GRID_SIZE + col + 1] ~= val then
                    match = false
                    break
                end
            end
            if match then return val end
        end
    end
    
    -- Check columns
    for col = 0, GRID_SIZE - 1 do
        local val = game.vars.grid[col + 1]
        if val ~= 0 then
            local match = true
            for row = 1, GRID_SIZE - 1 do
                if game.vars.grid[row * GRID_SIZE + col + 1] ~= val then
                    match = false
                    break
                end
            end
            if match then return val end
        end
    end
    
    -- Check diagonals
    local val = game.vars.grid[1]
    if val ~= 0 then
        if game.vars.grid[5] == val and game.vars.grid[9] == val then
            return val
        end
    end
    
    val = game.vars.grid[3]
    if val ~= 0 then
        if game.vars.grid[5] == val and game.vars.grid[7] == val then
            return val
        end
    end
    
    return 0
end

function is_board_full()
    for i = 1, 9 do
        if game.vars.grid[i] == 0 then
            return false
        end
    end
    return true
end

function find_best_move()
    local best_score = -1000
    local best_move = nil
    
    for i = 1, 9 do
        if game.vars.grid[i] == 0 then
            game.vars.grid[i] = game.vars.ai
            local score = minimax(0, false)
            game.vars.grid[i] = 0
            
            if score > best_score then
                best_score = score
                best_move = i
            end
        end
    end
    
    return best_move or 5  -- Fallback to center
end

function minimax(depth, is_maximizing)
    local winner = check_winner()
    
    if winner == game.vars.ai then return 10 - depth end
    if winner == game.vars.player then return depth - 10 end
    if is_board_full() then return 0 end
    
    if is_maximizing then
        local best_score = -1000
        for i = 1, 9 do
            if game.vars.grid[i] == 0 then
                game.vars.grid[i] = game.vars.ai
                local score = minimax(depth + 1, false)
                game.vars.grid[i] = 0
                best_score = math.max(best_score, score)
            end
        end
        return best_score
    else
        local best_score = 1000
        for i = 1, 9 do
            if game.vars.grid[i] == 0 then
                game.vars.grid[i] = game.vars.player
                local score = minimax(depth + 1, true)
                game.vars.grid[i] = 0
                best_score = math.min(best_score, score)
            end
        end
        return best_score
    end
end

function reset_game()
    game.vars.grid = {}
    for i = 1, 9 do
        game.vars.grid[i] = 0
    end
    game.vars.winner = 0
end
