@tool
extends GridMap

var valid_gridmap = false
var null_or_not_gridmap = false
var meshlib_mismatch = false
var is_self = false

var interchangable_tiles_rotatable: Array
var interchangable_tiles_fixed: Array
var rotation_values = [0, 10, 16, 22]

enum ROTATION_METHODS {RESET, KEEP_ORIGINAL, RANDOM}


@export var target_gridmap: NodePath
@export var randomize = false: set = set_randomize
@export var rotation_method: ROTATION_METHODS = ROTATION_METHODS.RANDOM
@onready var target_gridmap_node = get_node(target_gridmap)


func _ready() -> void:
	if not Engine.is_editor_hint():
		set_process(false)
	set_physics_process(false)

func _process(delta: float) -> void:
	if not Engine.is_editor_hint() or randomize == false:
		return
	valid_gridmap = is_gridmap_valid()
	
	if !valid_gridmap:
		return
	generate_randomisation_rules()
	randomize_target_gridmap()
	randomize = false

func set_randomize(value: bool):
	randomize = value
	if not Engine.is_editor_hint():
		return
	set_process(value)

func is_gridmap_valid():
	if not Engine.is_editor_hint():
		set_process(false)
		return
	
	if target_gridmap_node != null and target_gridmap_node.is_class("GridMap"):
		
		if target_gridmap_node == self:
			is_self = true
		elif target_gridmap_node.mesh_library != mesh_library:
			print ("meshlib mismatch")
			meshlib_mismatch = true
			
		else:
			print ("valid gridmap given")
			return true
	else:
		print ("null or not a gridmap given")
		null_or_not_gridmap = true
	
	return false
	
func generate_randomisation_rules():
	var current_row = -99
	var temp_array: Array
	var used_cells = get_used_cells()
	var cell_loop_index = 0
	var cell_meshlib_index
	var row_changes = false
	var last_index_reached = false
	interchangable_tiles_rotatable.clear()
	interchangable_tiles_fixed.clear()
	used_cells.sort_custom(sort_by_z_position)
	#print (used_cells)
	
	if !valid_gridmap:
		return
	for cell in used_cells:
		current_row = cell.z
		if used_cells.size() > cell_loop_index + 1:
			
			if used_cells[cell_loop_index].z != used_cells[cell_loop_index + 1].z:

				row_changes = true
			else:
				row_changes = false
			cell_loop_index += 1
		else:
			
			row_changes = true
			last_index_reached = true
		
		cell_meshlib_index = get_cell_item(cell)
		temp_array.append(cell_meshlib_index)
		
		if row_changes == true:
			if current_row < 0:
				
				interchangable_tiles_rotatable.push_back(temp_array.duplicate(false))
			else:
				interchangable_tiles_fixed.push_back(temp_array.duplicate(false))
				
			temp_array.clear()
		if last_index_reached == true:
			print ("rotatable: " + str(interchangable_tiles_rotatable))
			print ("fixed: " + str(interchangable_tiles_fixed))
			
func set_random_gridmap_tile(target_index, refmap_subarray, cell, _random_rotation = false):
	var random_pick_ref_index = randi_range(0, refmap_subarray.size() - 1)
	var random_pick_meshlib_index = refmap_subarray[random_pick_ref_index]
	
	if _random_rotation:
		if rotation_method == ROTATION_METHODS.KEEP_ORIGINAL:
			target_gridmap_node.set_cell_item(cell, random_pick_meshlib_index, target_gridmap_node.get_cell_item_orientation(cell))
		elif rotation_method == ROTATION_METHODS.RESET:
			target_gridmap_node.set_cell_item(cell, random_pick_meshlib_index)
		else:
			target_gridmap_node.set_cell_item(cell, random_pick_meshlib_index, rotation_values[randi_range(0,3)])
	else:	
		target_gridmap_node.set_cell_item(cell, random_pick_meshlib_index, target_gridmap_node.get_cell_item_orientation(cell))
	
func randomize_target_gridmap():
	print ("gridmap randomize started")
	
	var index_in_refmap_found = false
	var sub_array_with_index = null
	for cell in target_gridmap_node.get_used_cells():
		var target_meshlib_index = target_gridmap_node.get_cell_item(cell)
		for refmap_subarray in interchangable_tiles_rotatable:
			if refmap_subarray.has(target_meshlib_index):
				
				set_random_gridmap_tile(target_meshlib_index, refmap_subarray, cell, true)
		for refmap_subarray in interchangable_tiles_fixed:
			if refmap_subarray.has(target_meshlib_index):
				set_random_gridmap_tile(target_meshlib_index, refmap_subarray, cell)
	print ("gridmap randomize finished")

func sort_by_z_position(a: Vector3, b: Vector3):
	if a.z < b.z:
		return true
	return false

