-- Used to generate AI rank data
-- AutoLevel is a GO function that ranks characters based on his number of loses vs wins
-- AutoLevel is palette dependent so if a char has a 12th palette OP mode that mode can have more rank than his normal one
local randomtest = {}

function randomtest.strtrim(s)
	return string.match(s,'^()%s*$') and '' or string.match(s,'^%s*(.*%S)')
end

function randomtest.map(func, table)
	local dest = {}
	for k, v in pairs(table) do
		dest[k] = func(v)
	end
	return dest
end

-- Ints variables
local tuyoiBorder = 0
local juuni = 12
local moudeta = {}
local rank = 0
local saikyou = false
local roster = {}
local debugText = ''
local numChars = 0
local nextChar = 1

function randomtest.addMoudeta(rank)
	moudeta[#moudeta + 1] = rank
	local max = math.floor(numChars / (math.min(numChars / (juuni * 10) + 3, juuni) * juuni))
	while #moudeta > max do
		table.remove(moudeta, 1)
	end
end

function randomtest.randRank()
	local r = 0
	while true do
		r = math.random(1, tuyoiBorder + juuni - 2);
		local notbroken = true
		for i = 1, #moudeta do
			if math.abs(moudeta[i] - r) <= math.floor(juuni / 3) then
				notbroken = false
				break
			end
		end
		if notbroken then
			break
		end
	end
	return r
end

function randomtest.eachAllChars(f)
	for cel = 1, #main.t_randomChars do
		f(main.t_randomChars[cel])
	end
end

function randomtest.rakuBenry()
	local alf = 'save/autolevel.save'
	local veljnz = {}
	local winct = {}
	local buf = '\239\187\191'
	local fp = io.open(alf, 'r')
	if fp then
		for line in fp:lines() do
			local tmp = main.f_strsplit(',', line)
			if #tmp >= 2 then
				for i = 1, 4 do
					if i == 4 then
						tmp[1] = string.sub(tmp[1], 4)
					else
						if string.byte(tmp[1], i) ~= string.byte(buf, i) then break end
					end
				end
				winct[tmp[1]] = randomtest.map(tonumber, main.f_strsplit(' ', randomtest.strtrim(tmp[2])))
			end
		end
		io.close(fp)
	end
	numChars = 0
	randomtest.eachAllChars(function(cel)
		numChars = numChars + 1
	end)
	local tuyoninzu = math.floor(numChars / (juuni * 10))
	if tuyoninzu < juuni - 1 then
		tuyoiBorder = math.floor(numChars / (tuyoninzu + 1))
		tuyoninzu = juuni - 1
	else
		tuyoiBorder = math.floor(numChars / juuni)
	end
	local total = 0
	local zero = {}
	local tsuyoshi = {}
	local rand = {}
	local kai = {}
	local bimyou = {}
	local tuyocnt = 0
	local ran = randomtest.randRank()
	randomtest.eachAllChars(function(cel)
		if #veljnz < cel * 12 then
			for i = #veljnz + 1, cel * 12 do
				veljnz[i] = 0
			end
		end
		local wins = winct[getCharFileName(cel)]
		local tmp = 0
		for j = 1, 12 do
			if wins and j <= #wins then
				total = total + wins[j]
				veljnz[cel * 12 + j] = wins[j]
				tmp = tmp + wins[j]
			else
				veljnz[cel * 12 + j] = 0
			end
		end
		if tmp >= tuyoiBorder then tuyocnt = tuyocnt + 1 end
		if tmp >= tuyoiBorder - juuni then table.insert(tsuyoshi, cel) end
		if tmp >= 1 and tmp <= juuni then table.insert(bimyou, cel) end
		if tmp > ran - juuni and tmp <= ran then table.insert(rand, cel) end
		if tmp == 0 then table.insert(zero, cel) end
		if tmp < 0 then table.insert(kai, cel) end
	end)
	function charAdd(cList, numAdd)
		if numAdd <= 0 then return end
		for i = 1, numAdd do
			if #cList == 0 then break end
			local cidx = math.random(1, #cList)
			table.insert(roster, cList[cidx])
			table.remove(cList, cidx)
		end
	end
	roster = {}
	nextChar = 1
	debugText = ''
	local numZero = #zero
	if numZero > 0 then
		charAdd(zero, numZero)
		charAdd(kai, tuyoninzu - numZero)
		rank = 0
	elseif #bimyou >= math.max(tuyoninzu * 20, math.floor((numChars * 3) / 20)) then
		charAdd(bimyou, #bimyou)
		rank = juuni
	else
		for n = 1, 3 do
			if #rand >= tuyoninzu then break end
			rand = {}
			ran = randomtest.randRank()
			randomtest.eachAllChars(function(cel)
				local tmp = 0
				for j = 1, 12 do
					tmp = tmp + veljnz[cel * 12 + j]
				end
				if tmp > ran-juuni and tmp <= ran then table.insert(rand, cel) end
			end)
		end
		debugText = ran .. ' ' .. #rand
		if #rand >= tuyoninzu then
			charAdd(rand, #rand)
			rank = ran
			randomtest.addMoudeta(rank)
		elseif tuyocnt >= tuyoninzu then
			charAdd(tsuyoshi, #tsuyoshi)
			rank = tuyoiBorder + juuni - 1
		else
			randomtest.addMoudeta(tuyoiBorder + (juuni - 2) - math.floor(juuni / 3))
			charAdd(kai, #kai)
			rank = -1
		end
	end
	if numZero == 0 then
		while total ~= 0 do
			local i = math.random(1, #veljnz)
			if total > 0 then
				veljnz[i] = veljnz[i] - 1
				total = total - 1
			else
				veljnz[i] = veljnz[i] + 1
				total = total + 1
			end
		end
	end
	randomtest.eachAllChars(function(cel)
		buf = buf .. getCharFileName(cel) .. ','
		for j = 1, 12 do
			buf = buf .. ' ' .. veljnz[cel * 12 + j]
		end
		buf = buf .. '\r\n'
	end)
	local alv = io.open(alf, 'wb')
	alv:write(buf)
	io.close(alv)
end

function randomtest.randSel(pno, winner)
	if winner > 0 and (pno == winner) == not saikyou then return end
	local team
	if rank == 0 or rank == 12 or saikyou then
		team = 0
	elseif rank < 0 then
		team = math.random(0, 2)
	else
		team = math.random(0, 1) * 2
	end
	setTeamMode(pno, team, math.random(1, 4))
	start.p[pno].teamMode = team
	local tmp = 0
	while tmp < 2 do
		tmp = selectChar(pno, roster[nextChar], getCharRandomPalette(roster[nextChar]))
		nextChar = nextChar + 1
		if nextChar > #roster then nextChar = 1 end
	end
end

-- Writes the ranked AI levels to a save file
-- This file is not used by AutoLevel
function randomtest.rosterTxt()
	local str = "Rank: " .. rank .. ' ' .. debugText
	for i = 1, #roster do
		str = str .. '\n' .. getCharFileName(roster[i])
	end
	local dscr = io.open('save/AI_Rank.save', 'w')
	dscr:write(str)
	io.close(dscr)
end

-- Sets AIs to level 8 (MAX level) and ints AutoLevel
function randomtest.init()
	for i = 1, 8 do
		setCom(i, 8)
	end
	setAutoLevel(true)
	setMatchNo(1)
	randomtest.rakuBenry()
	winner = 0
	wins = 0
	randomtest.rosterTxt()
	nextChar = 1
	saikyou = rank == tuyoiBorder + juuni - 1
end

-- This is executed first
function randomtest.run()
	clearColor(0, 0, 0)
	randomtest.init()
	refresh()
	clearSelected()
	while not esc() do
		randomtest.randSel(1, winner)
		randomtest.randSel(2, winner)
		local stage = start.f_setStage()
		start.f_setMusic(stage)
		loadStart()
		local oldwinner = winner
		winner = game()
		clearColor(0, 0, 0)
		if winner < 0 or esc() then break end
		oldwins = wins
		wins = wins + 1
		if winner ~= oldwinner then
			wins = 1
			setHomeTeam(winner == 1 and 2 or 1)
		end
		setMatchNo(wins)
		if winner <= 0 or wins >= 20 or wins == oldwins then
			randomtest.init()
		end
		refresh()
	end
	main.f_bgReset(motif[main.background].bg)
	main.f_fadeReset('fadein', motif[main.group])
	main.f_playBGM(true, motif.music.title_bgm, motif.music.title_bgm_loop, motif.music.title_bgm_volume, motif.music.title_bgm_loopstart, motif.music.title_bgm_loopend)
end

return randomtest
