local S = minetest.get_translator("lzr_infobooks")
local FS = function(...) return minetest.formspec_escape(S(...)) end
local F = minetest.formspec_escape

lzr_infobooks = {}

local registered_books = {}
local registered_bookshelves = {}
local current_bookshelf = nil
local current_bookshelf_selection_index = nil

lzr_infobooks.register_book = function(book_id, book_def)
	registered_books[book_id] = book_def
end
lzr_infobooks.register_bookshelf = function(bookshelf_id, bookshelf_def)
	registered_bookshelves[bookshelf_id] = bookshelf_def
end

lzr_infobooks.open_book_page = function(player_name, book_id, page_num)
	local book = registered_books[book_id]
	local max_page = #book.pages
	if page_num > max_page then
		page_num = max_page
	end
	local page = book.pages[page_num]
	local bg = "lzr_infobooks_ui_book_bg.png"
	if book.color then
		bg = bg .. "^(lzr_infobooks_ui_book_bg_overlay.png^[multiply:"..book.color..")"
	end
	local form = "formspec_version[7]size[13,8.53125]"..
		"background[0,0;13,8.53125;"..bg..";true]"..
		"label[0.65,0.52;"..F(page.title).."]"..
		"label[7.15,0.52;"..F(page.title).."]"
	if page.image or page.item_image then
		local itype
		if page.image then
			itype = "image"
		else
			itype = "item_image"
		end
		local images = page[itype]
		if type(images) ~= "table" then
			images = { images }
		end

		local x
		if page.image_annotations then
			x = 0.7
		else
			x = 1.885
		end
		local y = 1.17
		local h = 5.2
		local off = 5.59
		h = math.min(2.6, h / #images)
		off = math.min(2.795, off / #images)
		for i=1, #images do
			form = form .. itype.."["..x..","..y..";"..h..","..h..";"..images[i].."]"
			if page.image_annotations then
				form = form .. "label["..(x+off+0.2)..","..(y+off/2)..";"..F(page.image_annotations[i]).."]"
			end
			y = y + off
		end
	end
	form = form ..
		"textarea[7.15,1.3;5.2,5.72;;;"..F(page.text).."]"
	if page_num > 1 then
		form = form .. "style[prev_page;sound=lzr_infobooks_turn_page]" ..
		--~ Previous page button
		"button[0.65,7.15;1.3,1.04;prev_page;"..FS("<").."]"..
		"tooltip[prev_page;"..FS("Previous page").."]"
	end
	if page_num < max_page then
		form = form .. "style[next_page;sound=lzr_infobooks_turn_page]" ..
		--~ Next page button
		"button[11.05,7.15;1.3,1.04;next_page;"..FS(">").."]"..
		"tooltip[next_page;"..FS("Next page").."]"
	end
	minetest.show_formspec(player_name, "lzr_infobooks:book:"..book_id..":"..page_num, form)
end

lzr_infobooks.open_book = function(player_name, book_id)
	minetest.sound_play({name = "lzr_infobooks_open_book", gain = 0.4}, {to_player=player_name}, true)
	lzr_infobooks.open_book_page(player_name, book_id, 1)
end

lzr_infobooks.open_bookshelf = function(player_name, bookshelf_id)
	local books = registered_bookshelves[bookshelf_id].books

	local form = "formspec_version[7]size[6,5]"..
		"label[0.5,0.5;"..FS("Select a book:").."]"..
		"style[read;sound=]"..
		"button[1.5,3.5;3,1;read;"..FS("Read").."]"..
		"tablecolumns[text]"..
		"table[0.5,0.8;5,2.5;booklist;"
	for b=1, #books do
		local book = registered_books[books[b]]
		form = form .. F(book.title)
		if b < #books then
			form = form .. ","
		end
	end
	local idx = current_bookshelf_selection_index or 1
	form = form .. ";"..idx.."]"
	current_bookshelf = bookshelf_id
	current_bookshelf_selection_index = 1
	minetest.show_formspec(player_name, "lzr_infobooks:bookshelf:"..bookshelf_id, form)
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if string.sub(formname, 1, 13) ~= "lzr_infobooks" then
		current_bookshelf = nil
		current_bookshelf_selection_index = nil
		return
	end
	local split = string.split(formname, ":")
	if not split or not split[2] or not split[3] then
		return
	end
	local btype = split[2]
	if btype == "book" then
		if fields.quit then
			minetest.sound_play({name = "lzr_infobooks_close_book", gain = 0.4}, {to_player=player:get_player_name()}, true)
			if current_bookshelf then
				lzr_infobooks.open_bookshelf(player:get_player_name(), current_bookshelf)
			end
			return
		end
		local book_id = split[3]
		local page_num = tonumber(split[4])
		if not page_num then
			return
		end

		if fields.next_page then
			page_num = page_num + 1
			lzr_infobooks.open_book_page(player:get_player_name(), book_id, page_num)
		elseif fields.prev_page then
			page_num = math.max(1, page_num - 1)
			lzr_infobooks.open_book_page(player:get_player_name(), book_id, page_num)
		end
	elseif btype == "bookshelf" then
		if fields.quit then
			current_bookshelf = nil
			current_bookshelf_selection_index = nil
			return
		end
		local bookshelf_id = split[3]
		if fields.booklist then
			local expl = minetest.explode_table_event(fields.booklist)
			if expl.type == "DCL" then
				local bookshelf = registered_bookshelves[bookshelf_id]
				local book_id = bookshelf.books[expl.row]
				lzr_infobooks.open_book(player:get_player_name(), book_id)
			elseif expl.type == "CHG" then
				current_bookshelf_selection_index = expl.row
			elseif expl.type == "INV" then
				current_bookshelf_selection_index = nil
			end
			return
		end
		if fields.read then
			if current_bookshelf and current_bookshelf_selection_index then
				local bookshelf = registered_bookshelves[current_bookshelf]
				local book_id = bookshelf.books[current_bookshelf_selection_index]
				lzr_infobooks.open_book(player:get_player_name(), book_id)
			end
		end
	end
end)

dofile(minetest.get_modpath("lzr_infobooks").."/register.lua")
