local class = require("class")
local utils = require("utils")
local async_util = require("async_util")
local topics = require("ui_topics")

local ScanReaderController = class()

function ScanReaderController:init()
	self.visibleList = {}
end

--Iterate over all the ships, weapons, and intel but only grab the necessary data
function ScanReaderController:LoadData()
	require('scanreader_utils')
	
	local scans = scanreader_utils:getScans()
	if #scans > 0 then
		self:CreateEntries(scans)
	end
end

function ScanReaderController:initialize(document)
    self.document = document
	self.scans = nil
	
	---Load background choice
	self.document:GetElementById("main_background"):SetClass(ScpuiSystem:getBackgroundClass(), true)
	
	--For BtA: Set the class custom. This is a thing because Journal needs to be modular to SCPUI as well as BtA.
	--So eventually this will need a separate file to add it's own hooks into ui_topics that can then be referenced.
	--But for now we just brute force it.
	self.document:GetElementById("main_background"):SetClass("scan_reader_bg", true)

	---Load the desired font size from the save file
	self.document:GetElementById("main_background"):SetClass(("p1-" .. ScpuiSystem:getFontSize()), true)
	
	self.document:GetElementById("tech_btn_1"):SetPseudoClass("checked", false)
	self.document:GetElementById("tech_btn_2"):SetPseudoClass("checked", false)
	self.document:GetElementById("tech_btn_3"):SetPseudoClass("checked", false)
	self.document:GetElementById("tech_btn_4"):SetPseudoClass("checked", true)
	
	topics.techroom.initialize:send(self)
	
	self.document:GetElementById("play_cont"):SetClass("hidden", true)
	self.document:GetElementById("stop_cont"):SetClass("hidden", true)
	
	--Get all the data fresh each time in case there are changes
	self:LoadData()
	
	self.SelectedEntry = nil
	
	if #self.visibleList > 0 then
		self:SelectEntry(self.visibleList[1])
	end
	
end

function ScanReaderController:ChangeTechState(state)

	if state == 1 then
		topics.techroom.btn1Action:send()
	end
	if state == 2 then
		topics.techroom.btn2Action:send()
	end
	if state == 3 then
		topics.techroom.btn3Action:send()
	end
	if state == 4 then
		--This is where we are already, so don't do anything
		--topics.techroom.btn4Action:send()
	end
	
end

function ScanReaderController:CreateEntryItem(entry, index)
	
	local li_el = self.document:CreateElement("li")
	li_el:SetClass("list_element", true)
	
	local displayName = ba.XSTR(entry.name, entry.xstr)
	entry.displayName = displayName
	
	local name = "<span>" .. displayName .. "</span>"
	local new = "<span style=\"color:red;margin-left:10;\">NEW!</span>"
	
	local display = name
	
	if entry.seen == false then
		display = display .. new
	end

	li_el.inner_rml = display
	li_el.id = entry.name

	entry.key = li_el.id
	entry.Index = index
	
	table.insert(self.visibleList, entry)
	
	li_el:SetClass("button_1", true)
	li_el:AddEventListener("click", function(_, _, _)
		self:SelectEntry(entry)
	end)

	return li_el
end

function ScanReaderController:CreateEntries(list)

	local list_names_el = self.document:GetElementById("list_items_ul")

	ScpuiSystem:ClearEntries(list_names_el)

	for i, v in ipairs(list) do
		list_names_el:AppendChild(self:CreateEntryItem(v, i))
	end
end

function ScanReaderController:SelectEntry(entry)

	if entry == nil then
		return
	end

	if (self.SelectedEntry == nil) or (entry.key ~= self.SelectedEntry.key) then
		self.document:GetElementById(entry.key):SetPseudoClass("checked", true)

		self.SelectedIndex = entry.Index
		
		local text_el = self.document:GetElementById("scan_view")
		ScpuiSystem:ClearEntries(text_el)
	
		if self.SelectedEntry then
			local oldEntry = self.document:GetElementById(self.SelectedEntry.key)
			if oldEntry then
				oldEntry:SetPseudoClass("checked", false)
				if self.SelectedEntry.seen == false then
					--Set as seen and save
					require('scanreader_utils')
					scanreader_utils:setSeen(self.SelectedEntry.name)
					--Make sure we only remove "NEW!"
					if oldEntry.last_child.inner_rml == "NEW!" then
						oldEntry:RemoveChild(oldEntry.last_child)
					end
				end
			end
		end
		
		local thisEntry = self.document:GetElementById(entry.key)
		self.SelectedEntry = entry
		thisEntry:SetPseudoClass("checked", true)
		
		self:stop_audio()
		
		--Set the description text
		text_el.inner_rml = entry.text or ''
		text_el.scroll_top = 0
	end


end

function ScanReaderController:ClearEntry()

	self.document:GetElementById(self.SelectedEntry.key):SetPseudoClass("checked", false)
	self.SelectedEntry = nil

end

function ScanReaderController:global_keydown(element, event)
    if event.parameters.key_identifier == rocket.key_identifier.ESCAPE then
        event:StopPropagation()

        ba.postGameEvent(ba.GameEvents["GS_EVENT_MAIN_MENU"])
	elseif event.parameters.key_identifier == rocket.key_identifier.UP and event.parameters.ctrl_key == 1 then
		self:ChangeTechState(2)
	elseif event.parameters.key_identifier == rocket.key_identifier.DOWN and event.parameters.ctrl_key == 1 then
		self:ChangeTechState(4)
	elseif event.parameters.key_identifier == rocket.key_identifier.UP and event.parameters.shift_key == 1 then
		self:ScrollList(self.document:GetElementById("scan_list"), 0)
	elseif event.parameters.key_identifier == rocket.key_identifier.DOWN and event.parameters.shift_key == 1 then
		self:ScrollList(self.document:GetElementById("scan_list"), 1)
	elseif event.parameters.key_identifier == rocket.key_identifier.UP then
		self:ScrollText(self.document:GetElementById("scan_view"), 0)
	elseif event.parameters.key_identifier == rocket.key_identifier.DOWN then
		self:ScrollText(self.document:GetElementById("scan_view"), 1)
	elseif event.parameters.key_identifier == rocket.key_identifier.LEFT then
		self:select_prev()
	elseif event.parameters.key_identifier == rocket.key_identifier.RIGHT then
		self:select_next()
	elseif event.parameters.key_identifier == rocket.key_identifier.RETURN then
		--self:commit_pressed(element)
	elseif event.parameters.key_identifier == rocket.key_identifier.F1 then
		self:help_clicked(element)
	elseif event.parameters.key_identifier == rocket.key_identifier.F2 then
		self:options_button_clicked(element)
	end
end

function ScanReaderController:ScrollList(element, direction)
	if direction == 0 then
		element.scroll_top = element.scroll_top - 15
	else
		element.scroll_top = element.scroll_top + 15
	end
end

function ScanReaderController:ScrollText(element, direction)
	if direction == 0 then
		element.scroll_top = (element.scroll_top - 5)
	else
		element.scroll_top = (element.scroll_top + 5)
	end
end

function ScanReaderController:select_next()
	if #self.visibleList == 0 then return end
	
    local num = #self.visibleList
	
	if self.SelectedIndex == num then
		ui.playElementSound(element, "click", "error")
	else
		local count = 1
		while self.visibleList[self.SelectedIndex + count] ~= nil do
			count = count + 1
		end
		
		if (self.SelectedIndex + count) > num then
			ui.playElementSound(element, "click", "error")
		else
			self:SelectEntry(self.visibleList[self.SelectedIndex + count])
		end
	end
end

function ScanReaderController:select_prev()
	if #self.visibleList == 0 then return end
	
	if self.SelectedIndex == 1 then
		ui.playElementSound(element, "click", "error")
	else
		local count = 1
		while self.visibleList[self.SelectedIndex - count] ~= nil do
			count = count + 1
		end
		
		if (self.SelectedIndex - count) < 1 then
			ui.playElementSound(element, "click", "error")
		else
			self:SelectEntry(self.visibleList[self.SelectedIndex - count])
		end
	end
end

function ScanReaderController:waitForSound(sound)
	return async.run(function()
		while sound ~= nil and sound:isPlaying() do
			async.await(async.yield())
		end
	end, async.OnFrameExecutor)
end

function ScanReaderController:play_audio()
	if self.SelectedEntry == nil then return end
	
	if self.Audio ~= nil then
		self:stop_audio()
	end
	
	self.Audio = ad.openAudioStream(self.SelectedEntry.audio, AUDIOSTREAM_VOICE)
	self.Audio:play()
	
	self.document:GetElementById("play_cont"):SetClass("hidden", true)
	self.document:GetElementById("stop_cont"):SetClass("hidden", false)
	
	async.run(function()
		--Wait for sound to be finished playing
		async.await(ScanReaderController:waitForSound(self.Audio))
		self:stop_audio()
	end, async.OnFrameExecutor)
end

function ScanReaderController:stop_audio()
	if self.Audio ~= nil and self.Audio:isValid() then
		self.Audio:stop()
	end
	
	if self.SelectedEntry ~= nil then
		if self.SelectedEntry.audio ~= "<none>" then
			self.document:GetElementById("play_cont"):SetClass("hidden", false)
		else
			self.document:GetElementById("play_cont"):SetClass("hidden", true)
		end
		
		self.document:GetElementById("stop_cont"):SetClass("hidden", true)
	end
	
	self.Audio = nil
end

function ScanReaderController:commit_pressed(element)
    ui.playElementSound(element, "click", "success")
    ba.postGameEvent(ba.GameEvents["GS_EVENT_MAIN_MENU"])
end

function ScanReaderController:options_button_clicked(element)
    ui.playElementSound(element, "click", "success")
    ba.postGameEvent(ba.GameEvents["GS_EVENT_OPTIONS_MENU"])
end

function ScanReaderController:help_clicked(element)
    ui.playElementSound(element, "click", "success")
    
	self.help_shown  = not self.help_shown

    local help_texts = self.document:GetElementsByClassName("tooltip")
    for _, v in ipairs(help_texts) do
        v:SetPseudoClass("shown", self.help_shown)
    end
end

function ScanReaderController:unload()
	self.SelectedEntry = nil
	self:stop_audio()
end

return ScanReaderController
