interface = {}

interface.level = 0
interface.cur_level = nil
local module = 0
local book = false
local ram = emu.item(machine.devices[':maincpu'].items['0/00000000-0000ffff'])

function interface.setlevel()
	if (interface.cur_level == nil or interface.cur_level == interface.level) then
		return
	end
	interface.cur_level = interface.level
	local lcd_num = { 0x00ff, 0x400c, 0x377, 0x023f, 0x38c, 0x03bb, 0x03fb, 0x020f, 0x3ff, 0x03bf }
	send_input(":BUTTONS", 0x10, 0.5) -- Parameter
	send_input(":BUTTONS", 0x80, 0.5) -- Enter
	while machine:outputs():get_value("digit0") ~= lcd_num[interface.level+1] do
		send_input(":BUTTONS", 0x01, 0.5) -- Move Fore
	end
	send_input(":EXTRA", 0x01, 0.5) -- Monitor
end

function interface.setmodule()
	local tmp = 0
	if module == 2 then
		tmp = 2
	else
		tmp = module % 2
	end
	send_input(":BUTTONS", 0x40, 0.1) -- Function
	for i=1,3 do
		send_input(":BUTTONS", 0x01, 0.1) -- Move Fore
	end
	send_input(":BUTTONS", 0x80, 0.1) -- Enter
	while (machine:ioport().ports[":MODULE"]:read() ~= tmp) do
		send_input(":MODULE", 0x03, 0.1) -- PM10/PM11
	end
	send_input(":EXTRA", 0x01, 0.1) -- Monitor
	if module == 3 then
		book = true
	end
end

function interface.setup_machine()
	sb_reset_board(":board")
	book = false
	emu.wait(1.0)

	interface.setmodule()
	interface.cur_level = 0
	interface.setlevel()
end

function interface.set_pos(mode)
	if mode == 0 then
		send_input(":BUTTONS", 0x04, 1) -- Board
		sb_clear_board(":board")
		send_input(":BUTTONS", 0x80, 1) -- Enter
		return (":board")
	else
		local fig = {0x81,0x82,0x83,0x84,0x85,0x86,0x00,0x06,0x05,0x04,0x03,0x02,0x01}
		local adr = 0x8315
		local brd = {{  3, 5, 4, 2, 1, 4, 5, 3 },
			     {  6, 6, 6, 6, 6, 6, 6, 6 },
			     {  0, 0, 0, 0, 0, 0, 0, 0 },
			     {  0, 0, 0, 0, 0, 0, 0, 0 },
			     {  0, 0, 0, 0, 0, 0, 0, 0 },
			     {  0, 0, 0, 0, 0, 0, 0, 0 },
			     { -6,-6,-6,-6,-6,-6,-6,-6 },
			     { -3,-5,-4,-2,-1,-4,-5,-3 }}
		for y=1,8 do
			for x=1,8 do
				local p=get_piece_id(x,y)
				local z=fig[p+7]
				if p~=0 and p~=brd[y][x] then
					z=z|0x40
				end
				ram:write(adr+10*(y-1)+x-1,z)
			end
		end
		if mode==1 then
			ram:write(0x83a1,0x00)
			ram:write(0x83a2,0x80)
		else
			ram:write(0x83a1,0x80)
			ram:write(0x83a2,0x00)
		end
		send_input(":EXTRA", 0x01, 0.5) -- Monitor
	end
end

function interface.edit_game()
	send_input(":BUTTONS", 0x20, 0.5) -- Selection
	send_input(":BUTTONS", 0x80, 0.5) -- Enter
	send_input(":EXTRA", 0x01, 0.5) -- Monitor
	emu.wait(0.5)
end

function interface.start_play(init)
	send_input(":BUTTONS", 0x80, 1) -- Enter
end

function interface.is_selected(x, y)
	local led_tag = { "a", "b", "c", "d", "e", "f", "g", "h" }
	return machine:outputs():get_indexed_value("led_" .. led_tag[x], 9 - y) == 0
end

function interface.select_piece(x, y, event)
	if book and (event=="get") then
		send_input(":EXTRA", 0x02, 0.1) -- View
		send_input(":BUTTONS", 0x40, 0.1) -- Notation
		send_input(":BUTTONS", 0x01, 0.1) -- Move Fore
		local tmp=ram:read(0x8093)
		send_input(":EXTRA", 0x02, 0.1) -- View
		send_input(":EXTRA", 0x01, 0.1) -- Monitor
		if tmp==32 then
			while (machine:ioport().ports[":MODULE"]:read() ~= 0x02) do
				send_input(":MODULE", 0x03, 0.1) -- PM11
			end
			book = false
		end
	end
	sb_select_piece(":board", 1, x, y, event)
end

function interface.get_options()
	return { { "spin", "Level", "0", "0", "9"}, { "combo", "Module", "None", "None\tPM10 Opening\tPM11 Endgame\tBoth"}, }
end

function interface.set_option(name, value)
	if (name == "level") then
		local level = tonumber(value)
		if (level < 0 or level > 9) then
			return
		end
		interface.level = level
		interface.setlevel()
	elseif (name == "module") then
		local temp = value:sub(1,4)
		if (temp == "None") then
			module = 0
		elseif (temp == "PM10") then
			module = 1
		elseif (temp == "PM11") then
			module = 2
		elseif (temp == "Both") then
			module = 3
		end
		interface.setmodule()
	end
end

function interface.get_promotion(x, y)
	local d0 = machine:outputs():get_value("digit0") & 0xffff
	if     (d0 == 0xf730) then	return "q"
	elseif (d0 == 0x93b4) then	return "r"
	elseif (d0 == 0xd432) then	return "b"
	elseif (d0 == 0x91bf) then	return "n"
	end

	return nil
end

function interface.promote(x, y, piece)
	sb_promote(":board", x, y, piece)
	local right = -1
	if     (piece == "q") then	right = 0
	elseif (piece == "r") then	right = 1
	elseif (piece == "b") then	right = 2
	elseif (piece == "n") then	right = 3
	elseif (piece == "Q" or piece == "R" or piece == "B" or piece == "N") then
		interface.select_piece(x, y, "")
		send_input(":BUTTONS", 0x80, 1)
		interface.select_piece(x, y, "")
	end

	if (right ~= -1) then
		for i=1,right do
			send_input(":BUTTONS", 0x01, 1)
		end

		send_input(":BUTTONS", 0x80, 1)
	end
end

return interface
