local btaloadouts = {}

local loadoutHandler = require("lib_loadout_handler")
local topics = require("lib_ui_topics")

--Init the countermeasure slots
function btaloadouts:initCountermeasureSlots()
	--If we didn't load countermeasures from the save file, then init them
	if BtACustomLoadouts["countermeasures"] == nil then
		BtACustomLoadouts["countermeasures"]= {}
		for i = 1, loadoutHandler:GetNumSlots() do
			local ship = loadoutHandler:GetShipLoadout(i)
			local cmType = ""
			if ship.ShipClassIndex > 0 then
				cmType = self:GetDefaultCountermeasure(ship.ShipClassIndex)
			end

			BtACustomLoadouts["countermeasures"][i] = {ship.Name, cmType}
		end
	end
end

function btaloadouts:unloadCountermeasureSlots()
	BtACustomLoadouts["countermeasures"] = nil
end

--Empty the countermeasure slot
function btaloadouts:EmptyCountermeasureSlot(slot)

	if BtACustomLoadouts["countermeasures"] == nil then return end

	local ship = loadoutHandler:GetShipLoadout(slot)
	BtACustomLoadouts["countermeasures"][slot] = {ship.Name, ""}
end

--Get the default countermeasure type for the ship class
function btaloadouts:GetDefaultCountermeasure(shipIdx)
	return tb.ShipClasses[shipIdx].CountermeasureClass.Name
end

--Set the countermeasure slot to default
function btaloadouts:SetDefaultCountermeasure(slot)

	if BtACustomLoadouts["countermeasures"] == nil then return end

	local ship = loadoutHandler:GetShipLoadout(slot)
	local cmType = self:GetDefaultCountermeasure(ship.ShipClassIndex)
	BtACustomLoadouts["countermeasures"][slot] = {ship.Name, cmType}
end

--Set the countermeasure slot
function btaloadouts:SetCountermeasure(slot, cmType)

	if BtACustomLoadouts["countermeasures"] == nil then return end

	if self:isCountermeasureTypeValid(cmType) then
		local ship = loadoutHandler:GetShipLoadout(slot)
		BtACustomLoadouts["countermeasures"][slot] = {ship.Name, cmType}
	else
		ba.warning("Tried to set invalid countermeasure type " .. cmType .. "!")
	end
end

--Get the countermeasure in the slot
function btaloadouts:GetCountermeasure(slot)
	local cm = BtACustomLoadouts["countermeasures"][slot]
	return cm[2]
end

--Get the list of allowed countermeasures for a ship class
function btaloadouts:GetAllowedCountermeasures(shipIdx)
	local allowedCMs = {}
	if tb.ShipClasses[shipIdx]:hasCustomData() then
		local cm_string = tb.ShipClasses[shipIdx].CustomData["allowedCMs"]
		if cm_string ~= nil then
			local utils = require("lib_utils")
			allowedCMs = utils.split(cm_string, ",")
		end
	end

	return allowedCMs
end

--Return true if slot can have countermeasure type, false otherwise
function btaloadouts:isCountermeasureAllowed(slot, cmType)

	local ship = loadoutHandler:GetShipLoadout(slot)

	if cmType == self:GetDefaultCountermeasure(ship.ShipClassIndex) then
		return true
	end

	local allowedCMs = self:GetAllowedCountermeasures(ship.ShipClassIndex)

	if #allowedCMs <= 0 then
		return false
	end

	for j, v in pairs(allowedCMs) do
		if cmType == v then
			return true
		end
	end

	return false
end

--Get the list of valid countermeasure types
function btaloadouts:GetCountermeasureList()
	return BtACustomLoadouts["cm_types"]
end

--Get the number of valid countermeasure types
function btaloadouts:GetNumCountermeasureTypes()
	return #BtACustomLoadouts["cm_types"]
end

--Get the list of valid countermeasure types
function btaloadouts:GetCountermeasureInfo(index)
	return BtACustomLoadouts["cm_types"][index]
end

--Get if a countermeasure type is valid for a ship
function btaloadouts:isCountermeasureTypeValid(cm)
	for i = 1, self:GetNumCountermeasureTypes() do
		local v = self:GetCountermeasureInfo(i)
		if v == cm then
			return true
		end
	end

	return false
end

--Here we apply limits set by the Inventory system in BtA2
function btaloadouts:applyInventoryLimits()

	--Make a copy of Inventory temporarily so we can decrement ship availability
	--as we go without messing with the actual Inventory data
	local utils = require("lib_utils")
	local inventory = utils.copy(Backstock.current.ships)
	local priorities = self:getPriorityList()

	if inventory == nil then
		ba.error("Inventory list is invalid in loadout handler!")
	end

	if priorities == nil then
		ba.error("Priority list is invalid in loadout handler!")
	end

	for i=1, loadoutHandler:GetNumSlots() do
		local ship = loadoutHandler:GetShipLoadout(i)

		local wing = string.lower(ship.WingName)

		--Only apply Inventory limits to Alpha, Beta, and Gamma wings
		if utils.isOneOf(wing, "alpha", "beta", "gamma") then

			for _, v in pairs(inventory) do
				if v.name == tb.ShipClasses[ship.ShipClassIndex].Name then

					--We have this ship available, so decrement and continue
					if v.remaining > 0 then
						v.remaining = v.remaining - 1
					else --We ran out of this ship class. Now find a new one!
						--But first let's return its weapons
						for j = 1, #ship.Weapons_List do
							loadoutHandler:EmptyWeaponBank(i, j) --Mjn you fucking moron. Why didn't you do this in the first place?
						end
						v.remaining = 0
						local p_type = self:getShipPriority(v.name, priorities)
						local newShipClass = self:getNextShipFromInventory(inventory, p_type, priorities)
						if newShipClass then
							loadoutHandler:AddShipToSlot(i, newShipClass)
						else
							loadoutHandler:TakeShipFromSlot(i)
						end

					end

					break

				end
			end

		end
	end

end

--Find the next available ship. This will be updated with a better version soon (tm)
function btaloadouts:getNextShipFromInventory(inventory, p_type, priorities)

	if p_type == nil then
		ba.warning("Current ship does not have a priority type! Using next available ship in Inventory!")

		for i, v in pairs(inventory) do
			if v.remaining > 0 then
				v.remaining = v.remaining - 1
				local idx = tb.ShipClasses[v.name]:getShipClassIndex()

				return idx
			end
		end
	else
		for i = 1, #priorities do

			for _, n in ipairs(priorities[p_type]) do
				for _, v in pairs(inventory) do
					if v.name == n then
						if v.remaining > 0 then
							local idx = tb.ShipClasses[v.name]:getShipClassIndex()
							--Make sure this ship is allowed in this mission's loadout as well
							if loadoutHandler:GetShipInfo(idx) ~= nil then
								v.remaining = v.remaining - 1
								return idx
							end
						end
					end
				end
			end

			p_type = p_type + 1

			if p_type > #priorities then
				p_type = 1
			end

		end
	end

end

--Get a ship's priority type
function btaloadouts:getShipPriority(shipName, priorities)
	for i, _ in ipairs(priorities) do
		for _, v in ipairs(priorities[i]) do
			if v == shipName then
				return i
			end
		end
	end

	return nil
end

--Load the ship_priority.cfg data
function btaloadouts:getPriorityList()
	local json = require('dkjson')

	--Loadouts are explicitely not saved across mod versions
	local location = 'data/config'

	local file = nil
	local config = {}

	if cf.fileExists('ship_priority.cfg', '', true) then
		file = cf.openFile('ship_priority.cfg', 'r', location)
		config = json.decode(file:read('*a'))
		file:close()
		if not config then
			config = {}
		end
	end

	--Validate the list
	for i, _ in ipairs(config) do
		for _, v in ipairs(config[i]) do
			if not tb.ShipClasses[v]:isValid() then
				ba.warning("Ship '" .. v .. "' is not a valid ship!")
			end
		end
	end

	return config
end

function btaloadouts:BuildCountermeasureList(context, ship)

	--Is this a mission where CM selection is allowed?
	if string.sub(mn.getMissionFilename(), 1, 4) ~= "bta2" and mn.getMissionFilename() ~= "bta_ship_test" then
		return
	end

	context.cm_select_el = Element.As.ElementFormControlDataSelect(context.Document:GetElementById("cstm_dropdown_cont").first_child)
	context.Document:GetElementById("countermeasure_lock"):SetClass("hidden", true)
	context.Document:GetElementById("cstm_dropdown_title").first_child:SetClass("orange", false)

	ScpuiSystem:clearDropdown(context.cm_select_el)

	--Is this ship slot weapon locked?
	local ship = loadoutHandler:GetShipLoadout(context.currentShipSlot)
	if ship.isWeaponLocked then
		context.Document:GetElementById("countermeasure_lock"):SetClass("hidden", false)
		context.Document:GetElementById("cstm_dropdown_title").first_child:SetClass("orange", true)
		return
	end

	local allowedCMs = self:GetAllowedCountermeasures(ship.ShipClassIndex)

	--Does this ship have a list of allowed CM types?
	if #allowedCMs <= 0 then
		context.Document:GetElementById("countermeasure_select"):SetClass("hidden", true)
		return
	end

	if string.sub(mn.getMissionFilename(), 1, 6) ~= "bta2_m" and mn.getMissionFilename() ~= "bta_ship_test" then
		context.Document:GetElementById("countermeasure_select"):SetClass("hidden", true)
	else
		context.Document:GetElementById("countermeasure_select"):SetClass("hidden", false)
	end

	--Get the default countermeasure for the ship class
	local default = self:GetDefaultCountermeasure(ship.ShipClassIndex)

	--Now build the list
	for i = 1, self:GetNumCountermeasureTypes() do

		local cm = self:GetCountermeasureInfo(i)

		--Is the CM unlocked?
		if tb.WeaponClasses[cm].InTechDatabase then
			if self:isCountermeasureAllowed(context.currentShipSlot, cm) then
				context.cm_select_el:Add(cm, cm, i)
			end
		end
	end

end

function btaloadouts:SetCountermeasureDropdown(context)

	--Is this a mission where CM selection is allowed?
	if string.sub(mn.getMissionFilename(), 1, 4) ~= "bta2" and mn.getMissionFilename() ~= "bta_ship_test" then
		return
	end

	context.cm_select_el = Element.As.ElementFormControlDataSelect(context.Document:GetElementById("cstm_dropdown_cont").first_child)

	local cm = self:GetCountermeasure(context.currentShipSlot)

	if cm ~= nil then
		for i, v in pairs(context.cm_select_el.options) do
			if v.value == cm then
				context.cm_select_el.selection = i + 1
			end
		end
	else
		ba.error("No countermeasure type found for ship! How did we get here?! Abort!")
	end

end

function btaloadouts:ShowCountermeasure(context)

	context.cm_select_el = Element.As.ElementFormControlDataSelect(context.Document:GetElementById("cstm_dropdown_cont").first_child)

	local sel_val = ""

	if context.cm_select_el.options[context.cm_select_el.selection - 1] ~= nil then
		sel_val = context.cm_select_el.options[context.cm_select_el.selection - 1].value
	end

	-- Get the countermeasure data as if it were a loadout item

	local weaponClass = tb.WeaponClasses[sel_val]
	local data = topics.weapons.stats:send(weaponClass)
	data.Amount = 0
	data.Icon = weaponClass.SelectIconFilename
	data.Anim = weaponClass.SelectAnimFilename
	data.Name = weaponClass.Name
	data.Title = weaponClass.TechTitle
	data.Description = string.gsub(weaponClass.Description, "Level", "<br></br>Level")
	data.FireWait = weaponClass.FireWait
	data.Type = "countermeasure"
	data.Key = weaponClass.Name
	data.GeneratedIcon = {}
	data.Index = weaponClass:getWeaponClassIndex()
	topics.loadouts.initWeaponInfo:send(data)
	context:selectWeapon(data)

end

function btaloadouts:ChangeCountermeasure(context)

	--Is this a mission where CM selection is allowed?
	if string.sub(mn.getMissionFilename(), 1, 4) ~= "bta2" and mn.getMissionFilename() ~= "bta_ship_test" then
		return
	end

	context.cm_select_el = Element.As.ElementFormControlDataSelect(context.Document:GetElementById("cstm_dropdown_cont").first_child)

	local cur_cm = self:GetCountermeasure(context.currentShipSlot)

	local sel_val = ""

	if context.cm_select_el.options[context.cm_select_el.selection - 1] ~= nil then
		sel_val = context.cm_select_el.options[context.cm_select_el.selection - 1].value
	end

	if context.shipChange == nil then
		btaloadouts:ShowCountermeasure(context)
	end

	--Is the CM changing?
	if cur_cm == sel_val then
		return
	else
		btaloadouts:SetCountermeasure(context.currentShipSlot, sel_val)
	end

end

function btaloadouts:createDropdown(context, title)

	local select_el = context.Document:CreateElement("div")

	local dropdown_el = context.Document:CreateElement("div")
	dropdown_el.id = "dropdown_template"
	dropdown_el:SetClass("cstm_btn_panel_horz", true)

	local dropdown_img = context.Document:CreateElement("img")
	dropdown_img:SetAttribute("src", "ops-panel-horz.png")

	local dropdown_text_cont = context.Document:CreateElement("div")
	dropdown_text_cont.id = "cstm_horz_panel_text"
	dropdown_text_cont:SetClass("cstm_ops_left_header", true)

	local dropdown_text_span = context.Document:CreateElement("span")
	dropdown_text_span.id = "cstm_dropdown_title"
	dropdown_text_span:SetClass("cstm_dropdown_text_el", true)
	dropdown_text_span.inner_rml = title

	local select_wrap = context.Document:CreateElement("div")
	select_wrap.id = "cstm_horz_panel_wrapper"

	local dropdown_cont = context.Document:CreateElement("div")
	dropdown_cont.id = "cstm_dropdown_cont"

	local data_el = context.Document:CreateElement("dataselect")
	data_el:SetClass("dropdown_dataselect_el", true)
	data_el.fields = "display"
	data_el.valuefield = "serialized"

	dropdown_cont:AppendChild(data_el)
	select_wrap:AppendChild(dropdown_cont)

	dropdown_text_cont:AppendChild(dropdown_text_span)

	dropdown_el:AppendChild(dropdown_text_cont)
	dropdown_el:AppendChild(select_wrap)
	dropdown_el:AppendChild(dropdown_img)

	select_el:AppendChild(dropdown_el)

	ship_select_el = Element.As.ElementFormControlDataSelect(dropdown_cont.first_child)

	return select_el, ship_select_el, data_el
end

function btaloadouts:M3_07_load(context)

	local md = require("debugFunctions")

	md.print("Red Alert is starting special loading functions for bta2_m3_07!")

	local parent = ScpuiSystem:getRootParent(context.Document)

	--Table of fighternames
	--May need to consider XSTR here?
	context.shipnames = {
		"None",
		"Alpha 1",
		"Alpha 2",
		"Alpha 3",
		"Alpha 4",
		"Beta 1",
		"Beta 2",
		"Beta 3"
	}

	--Start with the backup save
	local savefilename = "bta2_m3_06_ra_bak"
	if ShipSave:saveexist(savefilename) == false then
		md.print("Red Alert could not find the relevant save/load data!")
		return
	end
	ShipSave:load_init(savefilename)
	context.ra_saved_data = ShipSave:getData()

	--Now init the actual save to hack into
	local savefilename = "bta2_m3_06_ra"
	if ShipSave:saveexist(savefilename) == false then
		md.print("Red Alert could not find the relevant save/load data!")
		return
	end
	ShipSave:load_init(savefilename)

	context.ra_ships = {}

	--Get the ships of the wings in this mission and append to a table
	table.insert(context.ra_ships, context.ra_saved_data.ships["Alpha 1"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Alpha 2"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Alpha 3"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Alpha 4"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Beta 1"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Beta 2"][1][2])
	table.insert(context.ra_ships, context.ra_saved_data.ships["Beta 3"][1][2])

	context.ra_new_ships = context.ra_ships

	for i, v in pairs(context.ra_new_ships) do
		md.print("Red alert got ship " .. v .. " in slot " .. i)
	end

	local select_el_1, ship_select_el_1, data_el_1 = self:createDropdown(context, ba.XSTR("Assign to PVF Seth", 9245))
	select_el_1.id = "hol_ship_1_select"
	select_el_1.style.position = "absolute"
	select_el_1.style.right = "22%"
	select_el_1.style.bottom = "35%"
	select_el_1.style.width = "15%"
	parent:AppendChild(select_el_1)
	ScpuiSystem:clearDropdown(ship_select_el_1)
	ScpuiSystem:buildSelectList(ship_select_el_1, context.shipnames)
	ship_select_el_1.selection = 1
	data_el_1:AddEventListener("change", function(_, _, _)
		local sel_val = ""
		if ship_select_el_1.options[ship_select_el_1.selection - 1] ~= nil then
			sel_val = ship_select_el_1.options[ship_select_el_1.selection - 1].value
		end

		local idx = 0
		for i, v in ipairs(context.shipnames) do
			if v == sel_val then
				idx = i - 1
			end
		end

		context.ra_new_ships[idx] = "PVF Seth"
	end)

	select_el_2, ship_select_el_2, data_el_2 = self:createDropdown(context, ba.XSTR("Assign to PVF Horus", 9246))
	select_el_2.id = "hol_ship_2_select"
	select_el_2.style.position = "absolute"
	select_el_2.style.right = "5%"
	select_el_2.style.bottom = "35%"
	select_el_2.style.width = "15%"
	parent:AppendChild(select_el_2)
	ScpuiSystem:clearDropdown(ship_select_el_2)
	ScpuiSystem:buildSelectList(ship_select_el_2, context.shipnames)
	ship_select_el_2.selection = 1
	data_el_2:AddEventListener("change", function(_, _, _)
		local sel_val = ""
		if ship_select_el_2.options[ship_select_el_2.selection - 1] ~= nil then
			sel_val = ship_select_el_2.options[ship_select_el_2.selection - 1].value
		end

		local idx = 0
		for i, v in ipairs(context.shipnames) do
			if v == sel_val then
				idx = i - 1
			end
		end

		context.ra_new_ships[idx] = "PVF Horus"
	end)

	md.print("Red Alert ran special loading functions for bta2_m3_07!")

end

function btaloadouts:M3_07_cms(context, shipName)

	local md = require("debugFunctions")

	if context.ra_saved_data.ships[shipName][1][1] == -1 then
		ba.error("Ship " .. shipName .. " was destroyed in the m3_06! How did that happen?! Get Mjn!")
	end

	local class = context.ra_saved_data.ships[shipName][1][2]
	local cur_cm = context.ra_saved_data.ships[shipName][1][6][2]
	local species = tb.ShipClasses[class].Species

	--Vasudan
	if species.Name == "Parliamentary Vasudan Navy" or species.Name == "Hammer of Light" then
		if cur_cm == "AN/ALE-650" then
			cur_cm = "RIVCM-650"
		end
	else
		if cur_cm == "RIVCM-650" then
			cur_cm = "AN/ALE-650"
		end
	end

	local cmCargo = tb.ShipClasses[class].CountermeasuresMax
	local cmSize = tb.WeaponClasses[cur_cm].CargoSize
	local amount = cmCargo/cmSize

	md.print("Red Alert set the countermeasure for " .. shipName .. " (Class: " .. class .. ") to " .. cur_cm .. " with amount " .. amount .. "!")

	context.ra_saved_data.ships[shipName][1][6][2] = tb.WeaponClasses[cur_cm].Name
	context.ra_saved_data.ships[shipName][1][6][1] = amount

end

function btaloadouts:M3_07_save(context)

	local md = require("debugFunctions")

	md.print("Red Alert is starting special saving functions for bta2_m3_07!")

	if context.ra_saved_data == nil then
		md.print("Red Alert could not find the relevant save/load data!")
		return
	end

	context.ra_saved_data.ships["Alpha 1"][1][2] = context.ra_new_ships[1]
	context.ra_saved_data.ships["Alpha 2"][1][2] = context.ra_new_ships[2]
	context.ra_saved_data.ships["Alpha 3"][1][2] = context.ra_new_ships[3]
	context.ra_saved_data.ships["Alpha 4"][1][2] = context.ra_new_ships[4]
	context.ra_saved_data.ships["Beta 1"][1][2] = context.ra_new_ships[5]
	context.ra_saved_data.ships["Beta 2"][1][2] = context.ra_new_ships[6]
	context.ra_saved_data.ships["Beta 3"][1][2] = context.ra_new_ships[7]

	self:M3_07_cms(context, "Alpha 1")
	self:M3_07_cms(context, "Alpha 2")
	self:M3_07_cms(context, "Alpha 3")
	self:M3_07_cms(context, "Alpha 4")
	self:M3_07_cms(context, "Beta 1")
	self:M3_07_cms(context, "Beta 2")
	self:M3_07_cms(context, "Beta 3")

	ShipSave:setData(context.ra_saved_data)
	ShipSave:saveshipfile()

	md.print("Red Alert ran special saving functions for bta2_m3_07!")

end

return btaloadouts
