--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- содержит функции для работы с gameplay.xml - описание геймплея в динамике
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

local g_Gameplay = {}
local g_ShapesTable = {}
local complete_level_config = nil
-------------------------------------------------------------------------------------------------

function get_level_config(level)
	if not g_Gameplay[level] then complete_level_config(level) end
	return g_Gameplay[level]
end

-------------------------------------------------------------------------------------------------
local add_shapes = nil

function get_shapes(shapes, allowed_shapes)

	local shape_list = {}
	
	local size = table.getn(shapes)
	local count = size
	while count>1 do
		add_shapes(shapes[count], shape_list, allowed_shapes)
		count = count - 1
	end

	count = shapes[1]
	while count>0 do
		add_shapes(1, shape_list, allowed_shapes)
		count = count - 1
	end

	return shape_list
end



-------------------------------------------------------------------------------------------------
-- локальные функции
-------------------------------------------------------------------------------------------------
local function is_has_equal_in(shape, shape_list)
	local count = table.getn(shape_list)
	while count>0 do
		if g_ShapesTable[shape_list[count]][shape] then return true end
		count = count - 1
	end
	return false
end

-------------------------------------------------------------------------------------------------

local function enum_not_equal(shape_table, shape_list, allowed_shapes)
	local count = 0

	local i = table.getn(shape_table)
	while i>=0 do
		if shape_table[i] and allowed_shapes[i] then
			if not is_has_equal_in(i, shape_list) then count = count + 1 end
		end
		i = i - 1
	end
	
	return count
end

-------------------------------------------------------------------------------------------------

add_shapes = function(count, shape_list, allowed_shapes)
	log('generating '..count..' shapes')
	if count<=0 then return end

	local chance_number = 0
	local founded = {}
	local i = table.getn(g_ShapesTable)
	while i>=0 do
		if allowed_shapes[i]
		and g_ShapesTable[i].equal_count >= count - 1
		and (not is_has_equal_in(i, shape_list))
		and enum_not_equal(g_ShapesTable[i], shape_list, allowed_shapes) >= count then 
			chance_number = chance_number + 1
			founded[chance_number] = i
		end
		i = i - 1
	end

	if chance_number==0 then 
		error("Cannot generate shape list for level "..g_Player:GetLevel().." !")
	end

	chance_number = math.random(chance_number)
	i = founded[chance_number]

	local add_list = {}
	add_list[table.getn(add_list) + 1] = i
	count = count - 1
	log('listed shape '..i)

	local j = table.getn(g_ShapesTable[i])
	while j>=0 and count>0 do
		if g_ShapesTable[i][j] and i~=j and allowed_shapes[j] and not is_has_equal_in(j, shape_list) then
			add_list[table.getn(add_list) + 1] = j
			count = count - 1
			log('listed shape '..j)
		end
		j = j - 1
	end
	if count~=0 then error("Achtung! Cannot generate shape list for level "..g_Player:GetLevel().." !") end
	i = table.getn(add_list)
	while i>0 do
		shape_list[table.getn(shape_list) + 1] = add_list[i]
		log('added shape '..add_list[i])
		i = i - 1
	end
end

-------------------------------------------------------------------------------------------------

local function load_level_config(config)
	local level = {}

	level.location = tonumber(config:GetParameter(0))

	-- config:GetParameter(1) пропускаем - это номер уровня, для удобства дизайнеров

	level.image_setting = config:GetParameter(2)

	level.shapes_count_in_stripe = tonumber(config:GetParameter(3))

	level.stripe_speed = tonumber(config:GetParameter(4))

	level.colors_count = tonumber(config:GetParameter(5))

--	log('shapes '..config:GetParameter(6))
	level.shapes = parse_vector_from_string(config:GetParameter(6))

	level.allowed_shapes = {}
	local str = config:GetParameter(7)
	if str~= 'all' then
		allowed = parse_vector_from_string(str)
		local i = table.getn(allowed)
		while i>0 do
			level.allowed_shapes[allowed[i]] = true
--			log('allowed '..allowed[i])
			i = i - 1
		end
	else
		local shapes_num = table.getn(g_ShapesTable)
		while shapes_num>=0 do
			level.allowed_shapes[shapes_num] = true
			shapes_num = shapes_num - 1
		end
	end
	

	level.pause_chance = tonumber(config:GetParameter(8))

	level.revealer_chance = tonumber(config:GetParameter(9))

	level.gem_chance = tonumber(config:GetParameter(10))

	level.morph_chance = tonumber(config:GetParameter(11))

	level.switch_chance = tonumber(config:GetParameter(12))

	level.score_chance= tonumber(config:GetParameter(13))

	level.amulet_count = tonumber(config:GetParameter(14))

	level.goal_score = tonumber(config:GetParameter(15))

	level.sat_speed = tonumber(config:GetParameter(16))
	
	level.start_satisfaction = tonumber(config:GetParameter(17))
	

	-- сортируем описание фигур в порядке возрастания начиная со 2
--[[	local size = table.getn(level.shapes)
	local i = size
	while i>2 do
		local j = i - 1
		while j>1 do
			if level.shapes[i] < level.shapes[j] then
				local tmp = level.shapes[i]
				level.shapes[i] = level.shapes[j]
				level.shapes[j] = tmp
			end
			j = j - 1
		end
		i = i - 1
	end
]]
	g_Gameplay[table.getn(g_Gameplay) + 1] = level
end

-------------------------------------------------------------------------------------------------

local function load_config()
	g_Gameplay = {}
	local gconfig = CGameplayConfig(18)
	gconfig:LoadConfig('properties/gameplay.xml')
	local count = 0
	local size = gconfig:EnumConfigs()
	if size<100 then 
		size = 100
		gconfig:GetConfig(size-1)
	end
	local location = -1
	local start_level = 1
	while count<size do
		load_level_config(gconfig:GetConfig(count))
		count = count + 1
		if g_Gameplay[count].location~=location then
			start_level = count
			location = g_Gameplay[count].location
		end
		g_Gameplay[count].level = count - start_level + 1
	end
end

-------------------------------------------------------------------------------------------------

local function load_shapes_table(file)
	local f = io.open(file, "r")
	if not f then
		error("Cannot open file \""..file.."\"")
		return
	end

	local line = nil
	local shape = 0
	for line in f:lines() do
		g_ShapesTable[shape] = {}
		g_ShapesTable[shape].equal_count = 0
		local len = string.len(line)
		local pos = 1
		local shape2 = 0
		while pos<=len do
			if string.byte(line, pos)==49 then
				g_ShapesTable[shape][shape2] = true
				if shape~= shape2 then g_ShapesTable[shape].equal_count = g_ShapesTable[shape].equal_count + 1 end
			elseif string.byte(line, pos)==48 then
				g_ShapesTable[shape][shape2] = false
			else
				error("Shapes table contains incorrect symbols! ("..(shape+1).."x"..(shape2+1)..") = "..string.byte(line, pos))
			end
			pos = pos + 2
			shape2 = shape2 + 1
		end
		shape = shape + 1
	end
	io.close(f)
	
	local size = table.getn(g_ShapesTable)
	local i = size
	while i>=0 do
		if size~=table.getn(g_ShapesTable[i]) then
			error("Shapes table is not quadruple! ("..(i+1)..") size="..(table.getn(g_ShapesTable[i])+1))
		end
		local j = size
		while j>=0 do
			if g_ShapesTable[i][j]~=g_ShapesTable[j][i] then
				error("Shapes table is not symmetric! ("..(i+1).."x"..(j+1)..")")
			end
			j = j - 1
		end
		i = i - 1
	end
end

-------------------------------------------------------------------------------------------------
-- инициализация
-------------------------------------------------------------------------------------------------
load_shapes_table("properties\\shapes_table")
load_config()

