--Written by Brandon Evans

--You can change the number of controllers tracked here.
local controllers = 2
--You can change the position of the text here.
local x = 0
local y = 8

local players = {}
local states = {}
local pressed = 0
local inputted = 0

function table.copy(t)
	local t2 = {}
	for k, v in pairs(t) do
		t2[k] = v
	end
	return t2
end

function counts()
	--Display the counts of the buttons pressed and inputted.
	gui.text(x, y, 'Pressed: ' .. pressed)
	gui.text(x, y + 8, 'Inputted: ' .. inputted)
end

function load(slot)
	--As Lua starts counting from 1, and there may be a slot 0, increment.
	slot = slot + 1
	if not states[slot] or states[slot].inputted == nil then
		gui.text(x, y + 16, 'No data loaded from slot ' .. tostring(slot - 1))
		counts()
		return
	end
	--Load the data if there is any available for this slot.
	players = table.copy(states[slot].players)
	pressed = states[slot].pressed
	inputted = states[slot].inputted
	gui.text(x, y + 16, 'Data loaded from slot ' .. tostring(slot - 1))
	counts()
end

function parse()
	--If there is an open, read-only FM2 file, parse it for the initial data.
	if not movie.active() then
		return false
	end
	local fh = io.open(movie.name())
	if not fh or movie.mode() == 'record' or movie.name():match(
	'.%.(%w+)$'
	) ~= 'fm2' then
		return false
	end
	local frame = -1
	local last = {}
	local match = {
		'right', 'left', 'down', 'up', 'start', 'select', 'B', 'A'
	}
	--Parse up until two frames before the current one.
	while frame ~= emu.framecount() - 2 do
		line = fh:read()
		if not line then
			break
		end
		--This is only a frame if it starts with a vertical bar.
		if string.sub(line, 0, 1) == '|' then
			frame = frame + 1
			players = {}
			local player = -1
			--Split up the sections by a vertical bar.
			for section in string.gmatch(line, '[^|]+') do
				player = player + 1
				--Only deal with actual players.
				if player ~= 0 then
					local button = 0
					--Run through all the buttons.
					for text in string.gmatch(section, '.') do
						button = button + 1
						--Check if this button is pressed.
						if text ~= ' ' and text ~= '.' then
							inputted = inputted + 1
							--If the button was not previously pressed,
							--increment.
							if table.maxn(last) < player or not last[player][
								match[button]
							] then
								pressed = pressed + 1
							end
							if table.maxn(players) < player then
								table.insert(players, {})
							end
							--Mark this button as pressed.
							players[player][match[button]] = true
						end
					end
				end
			end
			--Save the players to compare with the next frame in the file.
			last = players
		end
	end
	return true
end

function save(slot)
	--As Lua starts counting from 1, and there may be a slot 0, increment.
	slot = slot + 1
	while table.maxn(states) < slot do
		table.insert(states, {})
	end
	--Mark the current data as the data for this slot.
	states[slot].players = table.copy(players)
	states[slot].pressed = pressed
	states[slot].inputted = inputted
	gui.text(x, y + 16, 'Data saved to slot ' .. tostring(slot - 1))
	counts()
end

if parse() then
	gui.text(x, y + 16, 'Movie parsed for data')
else
	gui.text(x, y + 16, 'No movie parsed for data')
end
if savestate.registerload then
	savestate.registerload(load)
	savestate.registersave(save)
end

while true do
	--If this is the first frame, reset the data.
	if emu.framecount() == 0 then
		players = {}
		pressed = 0
		inputted = 0
	end
	--Check players one and two.
	for player = 1, controllers do
		local buttons = joypad.getdown(player)
		--Run through all of the pressed buttons.
		for i, v in pairs(buttons) do
			inputted = inputted + 1
			--If in the previous frame the button was not pressed, increment.
			if table.maxn(players) >= player and not players[player][i] then
				pressed = pressed + 1
			end
		end
		if table.maxn(players) < player then
			table.insert(players, true)
		end
		--Mark these buttons as pressed.
		players[player] = buttons
	end
	counts()
	emu.frameadvance()
end
