interface = {}

interface.level = 6
interface.cur_level = nil
local throttled = true

function On() -- switch ON (if power OFF after 4 min.)
	if output:get_value("OFF") == 1 then
		send_input(":IN.1", 0x01, 0.5) -- ON/OFF
	end
end

function getdigit(n)
	local map = {{"s0.0","s0.21","s1.21","s1.22","s0.22","s1.0","s0.23"},
		     {"s0.4","s0.19","s1.19","s1.20","s0.20","s1.3","s0.3"},
		     {"s0.5","s0.16","s1.16","s1.17","s0.17","s1.5","s0.18"},
		     {"s0.9","s0.14","s1.14","s1.15","s0.15","s1.8","s0.8"},
		     {"s0.11","s0.12","s1.12","s1.13","s0.13","s1.10","s0.10"}}
	local dig = 0x00
	for i=1,7 do
		if (output:get_value(map[n][i]) ~= 0) then
			dig = dig | (1 << (i-1))
		end
	end
	return dig
end

function interface.setlevel()
	On()
	if (interface.cur_level == nil or interface.cur_level == interface.level) then
		return
	end
	local cl = interface.cur_level % 100
	local nl = interface.level % 100
	throttled = machine.video.throttled
	machine.video.throttled = false
	emu.wait(0.5)
	interface.cur_level = interface.level
	send_input(":IN.0", 0x08, 0.5) -- Level
	local val = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}
	local key
	local dig

	if (nl > cl and nl <= cl+50) or (nl < cl and nl <= cl-50) then
		key = ":IN.0"
	else
		key = ":IN.1"
	end
	local d5 = nl % 10
	local d4 = (nl - d5) / 10
	dig = val[d4 + 1]
	emu.wait(0.5)
	ioport.ports[key]:field(0x10):set_value(1) -- Right/Left on
	repeat
		emu.wait(0.1)
	until getdigit(4) == dig
	ioport.ports[key]:field(0x10):set_value(0) -- Right/Left off

	emu.wait(0.5)
	dig = getdigit(5)
	for i=0,9 do
		if dig == val[i+1] then
			cl = i
			break
		end
	end
	local dl = d5 - cl
	if dl > 0 then
		key = ":IN.0"
	else
		key = ":IN.1"
	end
	emu.wait(0.5)
	for i=1,math.abs(dl) do
		send_input(key, 0x10, 0.25) -- Right/Left
		emu.wait(0.5)
	end

	emu.wait(0.5)
	send_input(":IN.0", 0x08, 0.5) -- Level
	machine.video.throttled = throttled
end

function interface.setup_machine()
	sb_reset_board(":board")
--	send_input(":IN.1", 0x80, 2.5) -- New Game

	interface.cur_level = 6
	interface.setlevel()
end

function setpiece(n)
	if     (n == 1) then send_input(":IN.1", 0x02, 0.5) -- K
	elseif (n == 2) then send_input(":IN.0", 0x02, 0.5) -- Q
	elseif (n == 3) then send_input(":IN.0", 0x40, 0.5) -- R
	elseif (n == 4) then send_input(":IN.1", 0x40, 0.5) -- B
	elseif (n == 5) then send_input(":IN.0", 0x01, 0.5) -- N
	elseif (n == 6) then send_input(":IN.0", 0x80, 0.5) -- P
	end
end

function interface.set_pos(mode)
	On()
	if mode == 0 then
		send_input(":IN.0", 0x04, 0.5) -- Set Up
		send_input(":IN.1", 0x80, 0.5) -- Clear Board
		send_input(":IN.1", 0x80, 0.5) -- Clear Board
		return (":board")
	else
		local piece=7
		for y=1,8 do
			for x=1,8 do
				local p=get_piece_id(x,9-y)
				if p~=0 then
					if p*piece<0 then
						if p<0 then
							send_input(":IN.1", 0x10, 0.5) -- Left (Black)
						else
							send_input(":IN.0", 0x10, 0.5) -- Right (White)
						end
					end
					if math.abs(p)~=math.abs(piece) then
						setpiece(math.abs(p))
					end
					sb_press_square(":board", 0.5, x, 9-y)
					piece=p
				end
			end
		end
		if mode<0 then
			send_input(":IN.1", 0x10, 0.5) -- Left (Black)
		else
			send_input(":IN.0", 0x10, 0.5) -- Right (White)
		end
		send_input(":IN.0", 0x04, 0.5) -- Set Up
	end
end

function interface.edit_game()
	On()
	send_input(":IN.0", 0x20, 0.5) -- Multi Move
end

function interface.start_play()
	On()
	send_input(":IN.1", 0x04, 0.5) -- Move
end

function interface.is_selected(x, y)
	local xval = output:get_indexed_value("1.", 8 - x) ~= 0
	local yval = output:get_indexed_value("0.", y - 1) ~= 0
	return xval and yval
end

function interface.select_piece(x, y, event)
	On()
	emu.wait(0.5)
	if (event == "en_passant") then
		sb_remove_piece(":board", x, y)
		if interface.is_selected(x, y) then
			sb_press_square(":board", 0.5, x, y)
		end
	else
		local led = true
		if event == "get" then
			led = interface.is_selected(x, y)
		end
		sb_select_piece(":board", 0.5, x, y, event)
		if not led and not interface.is_selected(x, y) then
			sb_press_square(":board", 0.5, x, y)
		end
	end
end

function interface.get_options()
	return { { "spin", "Level", "6", "1", "100"}, }
end

function interface.set_option(name, value)
	if (name == "level") then
		local level = tonumber(value)
		if (level < 1 or level > 100) then
			return
		end
		interface.level = level
		interface.setlevel()
	end
end

function interface.test_promotion(x, y)
	On()
	emu.wait(0.5)
	for i=1,4 do
		if     output:get_value("s1.9") ~= 0 then
			send_input(":IN.0", 0x02, 0.5)
			return "Q"
		elseif output:get_value("s1.7") ~= 0 then
			send_input(":IN.0", 0x40, 0.5)
			return "R"
		elseif output:get_value("s1.6") ~= 0 then
			send_input(":IN.1", 0x40, 0.5)
			return "B"
		elseif output:get_value("s1.4") ~= 0 then
			send_input(":IN.0", 0x01, 0.5)
			return "N"
		end
		emu.wait(0.25)
	end
end

function interface.get_promotion(x, y)
	return nil
end

function interface.promote(x, y, piece)
	On()
	emu.wait(0.5)
	if     (piece == "q") then
		send_input(":IN.0", 0x02, 0.5)
	elseif (piece == "r") then
		send_input(":IN.0", 0x40, 0.5)
		send_input(":IN.0", 0x40, 0.5)
	elseif (piece == "b") then
		send_input(":IN.1", 0x40, 0.5)
		send_input(":IN.1", 0x40, 0.5)
	elseif (piece == "n") then
		send_input(":IN.0", 0x01, 0.5)
		send_input(":IN.0", 0x01, 0.5)
	end
	sb_promote(":board", x, y, piece)
end

return interface
