﻿-- chunkname: @scripts/extension_systems/side/side_system_tests.lua

local SideSystem

local function dummy_update_frame_tables(side)
	local human_units = side.valid_human_units
	local human_unit_positions = side.valid_human_units_positions
	local num_human_units = 0

	table.clear(human_units)
	table.clear(human_unit_positions)

	local human_and_bot_units = side.valid_player_units
	local human_and_bot_unit_positions = side.valid_player_units_positions
	local num_human_and_bot_units = 0

	table.clear(human_and_bot_units)
	table.clear(human_and_bot_unit_positions)

	local player_units = side:added_player_units()
	local num_player_units = #player_units

	for i = 1, num_player_units do
		local unit = player_units[i]
		local position = Vector3.zero()

		num_human_and_bot_units = num_human_and_bot_units + 1
		human_and_bot_units[num_human_and_bot_units] = unit
		human_and_bot_unit_positions[num_human_and_bot_units] = position
		human_and_bot_units[unit] = num_human_and_bot_units
		num_human_units = num_human_units + 1
		human_units[num_human_units] = unit
		human_unit_positions[num_human_units] = position
		human_units[unit] = num_human_units
	end
end

local function dummy_update_enemy_frame_tables(side)
	local human_units = side.valid_enemy_human_units
	local human_unit_positions = side.valid_enemy_human_units_positions
	local num_human_units = 0

	table.clear(human_units)
	table.clear(human_unit_positions)

	local human_and_bot_units = side.valid_enemy_player_units
	local human_and_bot_unit_positions = side.valid_enemy_player_units_positions
	local num_human_and_bot_units = 0

	table.clear(human_and_bot_units)
	table.clear(human_and_bot_unit_positions)

	local enemy_player_units = side:relation_player_units("enemy")
	local num_enemy_player_units = #enemy_player_units

	for i = 1, num_enemy_player_units do
		local unit = enemy_player_units[i]
		local position = Vector3.zero()

		num_human_and_bot_units = num_human_and_bot_units + 1
		human_and_bot_units[num_human_and_bot_units] = unit
		human_and_bot_unit_positions[num_human_and_bot_units] = position
		human_and_bot_units[unit] = num_human_and_bot_units
		num_human_units = num_human_units + 1
		human_units[num_human_units] = unit
		human_unit_positions[num_human_units] = position
		human_units[unit] = num_human_units
	end

	local ai_target_units = side.ai_target_units
	local num_ai_target_units = 0

	table.clear(ai_target_units)

	local enemy_units = side:relation_units("enemy")
	local num_enemy_units = #enemy_units

	for i = 1, num_enemy_units do
		local unit = enemy_units[i]

		num_ai_target_units = num_ai_target_units + 1
		ai_target_units[num_ai_target_units] = unit
		ai_target_units[unit] = num_ai_target_units
	end
end

local function dummy_create_side_system(side_compositions)
	local dummy_object = {}

	dummy_object._sides, dummy_object._side_lookup, dummy_object._side_names = SideSystem._create_sides(dummy_object, side_compositions)

	SideSystem._setup_relations(dummy_object, side_compositions, dummy_object._sides, dummy_object._side_lookup)

	dummy_object.side_by_unit = {}
	dummy_object._unit_extension_data = {}

	local class_table = CLASSES.SideSystem

	setmetatable(dummy_object, class_table)

	return dummy_object
end

local function init_and_run_tests(side_system_object)
	SideSystem = side_system_object

	local side_compositions = {
		{
			color_name = "red",
			name = "test1",
			relations = {
				enemy = {
					"test2",
					"test3",
				},
			},
		},
		{
			color_name = "blue",
			name = "test2",
			relations = {
				enemy = {
					"test1",
				},
			},
		},
		{
			color_name = "green",
			name = "test3",
			relations = {
				enemy = {
					"test1",
				},
			},
		},
	}
	local side_system = dummy_create_side_system(side_compositions)
	local unit_extension_data = side_system._unit_extension_data

	unit_extension_data.player_unit_1 = {
		is_player_unit = true,
		breed_tags = {},
	}
	unit_extension_data.player_unit_2 = {
		is_player_unit = true,
		breed_tags = {},
	}
	unit_extension_data.player_unit_3 = {
		is_player_unit = true,
		breed_tags = {},
	}
	unit_extension_data.minion_1 = {
		is_player_unit = false,
		breed_tags = {},
	}
	unit_extension_data.minion_2 = {
		is_player_unit = false,
		breed_tags = {},
	}
	unit_extension_data.minion_3 = {
		is_player_unit = false,
		breed_tags = {},
	}
	unit_extension_data.minion_4 = {
		is_player_unit = false,
		breed_tags = {},
	}
	unit_extension_data.minion_5 = {
		is_player_unit = false,
		breed_tags = {},
	}

	local sides = side_system._sides
	local side_1, side_2, side_3 = sides[1], sides[2], sides[3]

	side_system:_add_unit_to_side("player_unit_1", 1)
	side_system:_add_unit_to_side("player_unit_2", 1)
	side_system:_add_unit_to_side("player_unit_3", 1)

	for i = 1, #side_compositions do
		local side = sides[i]

		dummy_update_frame_tables(side)
		dummy_update_enemy_frame_tables(side)
	end

	side_system:_remove_unit_from_tag_units("player_unit_2", unit_extension_data.player_unit_2)
	side_system:_remove_unit_from_side("player_unit_2")

	for i = 1, #side_compositions do
		local side = sides[i]

		dummy_update_frame_tables(side)
		dummy_update_enemy_frame_tables(side)
	end

	side_system:_remove_unit_from_tag_units("player_unit_1", unit_extension_data.player_unit_1)
	side_system:_remove_unit_from_side("player_unit_1")
	side_system:_remove_unit_from_tag_units("player_unit_3", unit_extension_data.player_unit_3)
	side_system:_remove_unit_from_side("player_unit_3")

	for i = 1, #side_compositions do
		local side = sides[i]

		dummy_update_frame_tables(side)
		dummy_update_enemy_frame_tables(side)
	end

	side_system:_add_unit_to_side("minion_1", 1)
	side_system:_add_unit_to_side("minion_2", 2)
	side_system:_add_unit_to_side("minion_3", 2)
	side_system:_add_unit_to_side("minion_4", 3)
	side_system:_add_unit_to_side("minion_5", 3)
	side_system:add_aggroed_minion("minion_1")
	side_system:remove_aggroed_minion("minion_1")
	side_system:add_aggroed_minion("minion_1")
	side_system:add_aggroed_minion("minion_2")
	side_system:add_aggroed_minion("minion_3")
	side_system:add_aggroed_minion("minion_4")
	side_system:add_aggroed_minion("minion_5")
	side_system:remove_aggroed_minion("minion_1")
	side_system:remove_aggroed_minion("minion_2")
	side_system:remove_aggroed_minion("minion_3")
	side_system:remove_aggroed_minion("minion_4")
	side_system:remove_aggroed_minion("minion_5")
	side_system:_remove_unit_from_tag_units("minion_1", unit_extension_data.minion_1)
	side_system:_remove_unit_from_tag_units("minion_2", unit_extension_data.minion_2)
	side_system:_remove_unit_from_tag_units("minion_3", unit_extension_data.minion_3)
	side_system:_remove_unit_from_tag_units("minion_4", unit_extension_data.minion_4)
	side_system:_remove_unit_from_tag_units("minion_5", unit_extension_data.minion_5)
	side_system:_remove_unit_from_side("minion_1")
	side_system:_remove_unit_from_side("minion_2")
	side_system:_remove_unit_from_side("minion_3")
	side_system:_remove_unit_from_side("minion_4")
	side_system:_remove_unit_from_side("minion_5")
	side_system:destroy()
end

return init_and_run_tests
