extends Control

# DATA
# Holds board data such as x, o, and unmarked
var board : Array

# State of player, X or O
var player : String

# State for a winner or not
var is_winner: bool = false

# State for game over or not
var is_gameover: bool = false

# State for draw/tie or not
var is_draw: bool = false

# LOAD IMAGE FILES
# Button unpressed
var unpressed = preload("res://assets/unpressed-tile.png")

# Button for Player X
var player_x = preload("res://assets/player-x-tile.png")

# Button for Player O
var player_o = preload("res://assets/player-o-tile.png")

# Initiates board/game data
func initiate_board() -> void:
	board = [
		"0", "0", "0",
		"0", "0", "0",
		"0", "0", "0"
	]
	$Board/Row0/Button0.texture_normal = unpressed
	$Board/Row0/Button1.texture_normal = unpressed
	$Board/Row0/Button2.texture_normal = unpressed	
	$Board/Row1/Button3.texture_normal = unpressed
	$Board/Row1/Button4.texture_normal = unpressed
	$Board/Row1/Button5.texture_normal = unpressed
	$Board/Row2/Button6.texture_normal = unpressed
	$Board/Row2/Button7.texture_normal = unpressed
	$Board/Row2/Button8.texture_normal = unpressed
	is_gameover = false
	is_winner = false
	is_draw = false	

# Initiates a player
func initiate_player() -> void:
	player = "x"

# Runs automatically when scene is loaded
func _ready() -> void:
	$GameOverMessage.hide()
	initiate_board()
	initiate_player()

# Next player's turn
func update_player() -> void:
	if player == "x":
		player = "o"
	else:
		player = "x"

# Check rows for a match 3
func is_row_matched() -> bool:
	var offset = 0
	for row in range(3):
		for index in range(0 + offset, 3 + offset):
			if board[index] == player:
				is_winner = true
			else:
				is_winner = false
				break
		if is_winner:
			return true
		offset += 3
	return false

# Check columns for a match 3
func is_col_matched() -> bool:
	var offset = 0
	for col in range(3):
		for index in range(0 + offset, 7 + offset, 3):
			if board[index] == player:
				is_winner = true
			else:
				is_winner = false
				break
		if is_winner:
			return true
		offset += 1
	return false
	
# Check diagonals for a match 3
func is_diag_matched() -> bool:
	for i in range(0, 9, 4):
		if board[i] == player:
			is_winner = true
		else:
			is_winner = false
			break
	if is_winner:
		return true
	for i in range(2, 7, 2):
		if board[i] == player:
			is_winner = true
		else:
			is_winner = false
			break
	if is_winner:
		return true
	return false

# Check if board is full
func is_board_full() -> bool:
	if board.has("0"):
		return false
	return true

# Check for win/draw conditions
func check_gameover() -> void:
	if is_row_matched() || is_col_matched() || is_diag_matched():
		is_gameover = true
		add_gameover_message()
	elif is_board_full():
		is_gameover = true
		is_draw = true
		add_gameover_message()

# Show a gameover message
func add_gameover_message() -> void:
	if is_draw:
		$GameOverMessage/Container/Label.text = "Game is a draw!"
	else:
		$GameOverMessage/Container/Label.text = "Player " + player + " wins!"
	$GameOverMessage.show()

# Mark player's move
func make_move(index: int) -> void:
	board[index] = player
	check_gameover()

# Check if button/square is free or open
func is_square_free(index: int) -> bool:
	if board[index] == "0":
		return true
	return false

# Update board with X or O button image
func update_board(row: int, index: int) -> void:
	var path = "Board/Row" + String(row) + "/Button" + String(index)
	if player == "x":
		get_node(path).texture_normal = player_x
	elif player == "o":
		get_node(path).texture_normal = player_o
	update_player()
	
# SIGNALS
# Signal for button 0
func _on_Button0_button_up() -> void:
	if is_square_free(0) && !is_gameover:
		make_move(0)
		update_board(0, 0)

# Signal for button 1
func _on_Button1_button_up() -> void:
	if is_square_free(1) && !is_gameover:
		make_move(1)
		update_board(0, 1)

# Signal for button 2
func _on_Button2_button_up() -> void:
	if is_square_free(2) && !is_gameover:
		make_move(2)
		update_board(0, 2)

# Signal for button 3
func _on_Button3_button_up() -> void:
	if is_square_free(3) && !is_gameover:
		make_move(3)
		update_board(1, 3)

# Signal for button 4
func _on_Button4_button_up() -> void:
	if is_square_free(4) && !is_gameover:
		make_move(4)
		update_board(1, 4)

# Signal for button 5
func _on_Button5_button_up() -> void:
	if is_square_free(5) && !is_gameover:
		make_move(5)
		update_board(1, 5)

# Signal for button 6
func _on_Button6_button_up() -> void:
	if is_square_free(6) && !is_gameover:
		make_move(6)
		update_board(2, 6)

# Signal for button 7
func _on_Button7_button_up() -> void:
	if is_square_free(7) && !is_gameover:
		make_move(7)
		update_board(2, 7)

# Signal for button 8
func _on_Button8_button_up() -> void:
	if is_square_free(8) && !is_gameover:
		make_move(8)
		update_board(2, 8)

# Signal for restart button
func _on_RestartButton_button_up() -> void:
	$GameOverMessage.hide()
	initiate_board()
	initiate_player()