local utils = require("utils")
local tblUtil = utils.table
local dialogs = require("dialogs")
local class = require("class")
local datasaver = require("datasaver")

local PersonnelController = class()

function PersonnelController:init()
end

function PersonnelController:initialize(document)

    self.document = document

    ---Load background choice
    self.document:GetElementById("main_background"):SetClass(ScpuiSystem:getBackgroundClass(), true)
    
    ---Load the desired font size from the save file
	self.document:GetElementById("main_background"):SetClass(("base_font" .. ScpuiSystem:getFontPixelSize()), true)
    
    self.saveData = datasaver:loadDataFromFile("personnel", true) or {}
	
	--Get the key for the game progression
	self.Key = self:getPlayerProgress()
	
	Personnel:sortEntries(self.Key)

    self.SelectedEntry = nil

    self:CreateEntries()
    
end

function PersonnelController:getPlayerProgress()
	local BtA = require("btafunctions")
	return BtA:getGameProgress()
end

function PersonnelController:getProgressionOverride(entry)
	for i, v in pairs(entry.Progression) do
		if self.Key >= v.Key then
			return v
		end
	end
	
	return nil
end

function PersonnelController:sortEntries()

	local function splitName(name)
		local first, last = name:match("(%S+)%s+(%S+)")
		return first, last
	end
	
    table.sort(Personnel.entries, function(a, b)
        -- First compare affiliations
        if a.Affiliation ~= b.Affiliation then
            return a.Affiliation < b.Affiliation
        end
        
        -- If affiliations are the same, compare last names
        local aFirst, aLast = splitName(a.Name)
        local bFirst, bLast = splitName(b.Name)
        
        if aLast ~= bLast then
            return aLast < bLast
        end
        
        -- If last names are the same, compare first names
        return aFirst < bFirst
    end)
end

function PersonnelController:formatNameToButton(name, suffix)
	local lowerName = name:lower()
	local formattedName = lowerName:gsub("%s", "_")
	return formattedName .. suffix
end

function PersonnelController:CreateEntryItem(entry)

	local lastRead = self.saveData[entry.Name]
	
	local function insertCallsign(name, callsign)
		local first, last = name:match("(%S+)%s+(%S+)")
		
		if first and last and callsign and callsign ~= "" then
			return first .. ' "' .. callsign .. '" ' .. last
		else
			return name
		end
	end
	
	local callsign = entry.Callsign
	local affiliation = entry.Affiliation
	
	--Check for overrides
		local override = self:getProgressionOverride(entry)
		if override ~= nil then
			if override.Callsign then
				callsign = override.Callsign
			end
			if override.Affiliation then
				affiliation = override.Affiliation
			end
		end

    local el = self.document:CreateElement("div")
	el.id = self:formatNameToButton(entry.Name, "_button")
	el:SetClass("portrait", true)
	el:SetClass("button_1", true)
    el:AddEventListener("click", function(_, _, _)
        self:SelectEntry(entry)
    end)
	
    local img_el = self.document:CreateElement("img")
	img_el:SetAttribute("src", entry.File)
	el:AppendChild(img_el)
	
	local name_el = self.document:CreateElement("div")
	name_el:SetClass("name", true)
	name_el.inner_rml = insertCallsign(entry.Name, callsign)
	el:AppendChild(name_el)
	
	local new_el = self.document:CreateElement("div")
	new_el.id = self:formatNameToButton(entry.Name, "_new")
	new_el:SetClass("new", true)
	new_el.inner_rml = "!"
	el:AppendChild(new_el)
	if not lastRead or  (lastRead < self.Key and override) then
		new_el:SetClass("hidden", false)
	else
		new_el:SetClass("hidden", true)
	end
	
	if affiliation then
		local faction = Factions:getFactionByAcronym(affiliation)
		local logo_el = self.document:CreateElement("img")
		logo_el:SetClass("logo", true)
		logo_el:SetAttribute("src", faction.Logo)
		el:AppendChild(logo_el)
	end

    return el
    
end

function PersonnelController:CreateEntries()

	local parent_el = self.document:GetElementById("portrait_grid")
	
	local faction = nil
	local faction_group_el = nil

    for i, v in ipairs(Personnel.entries) do
		ba.print("Adding entry " .. i .. ": " .. v.Name .. "\n" )
		
		--Get the current affiliation
		local affiliation = v.Affiliation
		--Check for overrides
		local override = self:getProgressionOverride(v)
		if override ~= nil then
			if override.Affiliation then
				affiliation = override.Affiliation
			end
		end
		if not affiliation then
			affiliation = "OTHER"
		end
		
		if faction ~= affiliation then
			faction = affiliation
			faction_el = self.document:CreateElement("div")
			faction_el:SetClass("faction", true)
			faction_el.inner_rml = Factions:getFactionByAcronym(affiliation).DisplayName
			parent_el:AppendChild(faction_el)
			
			faction_group_el = self.document:CreateElement("div")
			faction_group_el:SetClass("faction_group")
			parent_el:AppendChild(faction_group_el)
		end
		faction_group_el:AppendChild(self:CreateEntryItem(v))
    end
end

function PersonnelController:CreateBioDetail(header, value)
	local el = self.document:CreateElement("div")
	el:SetClass("bio_detail", true)
	
	local header_el = self.document:CreateElement("span")
	header_el:SetClass("bio_header", true)
	header_el.inner_rml = header .. ": "
	el:AppendChild(header_el)
	
	local value_el = self.document:CreateElement("span")
	value_el:SetClass("bio_value", true)
	value_el.inner_rml = value
	el:AppendChild(value_el)
	
	return el
end

function PersonnelController:FormatHeight(height)
	return string.format("%.2fm", height)
end

function PersonnelController:FormatWeight(weight)
	return string.format("%.1fkg", weight)
end

function PersonnelController:SelectEntry(entry)

	local key = self:formatNameToButton(entry.Name, "_button")

    if key ~= self.SelectedEntry then
        
		if self.SelectedEntry then
			local oldEntry = self.document:GetElementById(self.SelectedEntry)
			if oldEntry then oldEntry:SetPseudoClass("checked", false) end
		end
		
		local thisEntry = self.document:GetElementById(key)
		self.SelectedEntry = key
		thisEntry:SetPseudoClass("checked", true)
		
		self.saveData[entry.Name] = self.Key
		datasaver:saveDataToFile("personnel", self.saveData, true)
		
		local new_el = self.document:GetElementById(self:formatNameToButton(entry.Name, "_new"))
		new_el:SetClass("hidden", true)
		
		local biography = entry.Biography
		local callsign = entry.Callsign
		local rank = entry.Rank
		local position = entry.Position
		local posting = entry.Posting
		local commendations = entry.Commendations
		local height = entry.Height
		local weight = entry.Weight
		local gender = entry.Gender
		local affiliation = entry.Affiliation
		
		--Check for overrides
		local override = self:getProgressionOverride(entry)
		if override ~= nil then
			if override.Biography then
				biography = override.Biography
			end
			if override.Callsign then
				callsign = override.Callsign
			end
			if override.Rank then
				rank = override.Rank
			end
			if override.Position then
				position = override.Position
			end
			if override.Posting then
				posting = override.Posting
			end
			if override.Commendations then
				commendations = override.Commendations
			end
			if override.Height then
				height = override.Height
			end
			if override.Weight then
				weight = override.Weight
			end
			if override.Gender then
				gender = override.Gender
			end
			if override.Affiliation then
				affiliation = override.Affiliation
			end
		end
		
		local details_el = self.document:GetElementById("portrait_details")
		ScpuiSystem:ClearEntries(details_el)
		
		local name_el = self:CreateBioDetail("Name", entry.Name)
		name_el:SetClass("bio_name", true)
		name_el:SetClass("bio_detail", false)
		details_el:AppendChild(name_el)
		
		if callsign then
			local el = self:CreateBioDetail("Callsign", callsign)
			details_el:AppendChild(el)
		end
		if rank then
			local el = self:CreateBioDetail("Rank", rank)
			details_el:AppendChild(el)
		end
		if position then
			local el = self:CreateBioDetail("Position", position)
			details_el:AppendChild(el)
		end
		if posting then
			local el = self:CreateBioDetail("Posting", posting)
			details_el:AppendChild(el)
		end
		if commendations then
			local el = self:CreateBioDetail("Commendations", commendations)
			details_el:AppendChild(el)
		end
		if height then
			local el = self:CreateBioDetail("Height", self:FormatHeight(height))
			details_el:AppendChild(el)
		end
		if weight then
			local el = self:CreateBioDetail("Weight", self:FormatWeight(weight))
			details_el:AppendChild(el)
		end
		if gender then
			local el = self:CreateBioDetail("Pronouns", gender)
			details_el:AppendChild(el)
		end
		if affiliation then
			local el = self:CreateBioDetail("Affiliation", Factions:getFactionByAcronym(affiliation).DisplayName)
			details_el:AppendChild(el)
		end
		
		local bio_el = self.document:CreateElement("div")
		bio_el:SetClass("bio_full", true)
		bio_el.inner_rml = biography
		details_el:AppendChild(bio_el)
	end

end

function PersonnelController:Exit(element)

    ui.playElementSound(element, "click", "success")
    ScpuiSystem:ReturnToState(ScpuiSystem.lastState)
    self.document:Close()

end

function PersonnelController:global_keydown(_, event)
    if event.parameters.key_identifier == rocket.key_identifier.ESCAPE then
        event:StopPropagation()
        self.document:Close()
        ScpuiSystem:ReturnToState(ScpuiSystem.lastState)
    end
end

return PersonnelController
