NUiShipWeapons = {}
NUiShipWeapons.DEBUG_FAKE_WEAPONS = false
NUiShipWeapons.WeaponPanelBottomY = 0.0

function NUiShipWeapons:SetupUI()
	require("nui-hud")

	self.Active = {}
	self.WeaponsLogged = false
	self:ParseConfig("nui-hud.tbl")

	if self.Active.WeaponsFrame then
		self:SetupWeaponsFrame()
	end

	if self.Active.WeaponOverheatBar then
		self:SetupWeaponOverheatBar()
	end
end

function NUiShipWeapons:ParseConfig(file)
	NUi:ParseGeneralSettings(file, self)

	NUi:ParseConfigSection(file, "#Weapons Frame Settings", function() self:ConfigWeaponsFrame() end)

	NUi:ParseConfigSection(file, "#Weapon Overheat Bar Settings", function() self:ConfigWeaponOverheatBar() end)
end

function NUiShipWeapons:ConfigWeaponsFrame()
	self.Active.WeaponsFrame = true

	local t = { Graphic = {}, Colors = {} }

	local frameOrigin = {1.0, 0.0}
	local frameOffset = {0, 30}
	t.PrimaryInactiveOffset   = 10
	t.SecondaryInactiveOffset = 10
	if parse.optionalString("$Weapon Frames:") then
		if parse.optionalString("+Origin:") then
			frameOrigin = NUi:GetCSV(parse.getString())
		end
		if parse.optionalString("+Offset:") then
			frameOffset = NUi:GetCSV(parse.getString())
			frameOffset[1] = frameOffset[1] * self.ScaleFactor
			frameOffset[2] = frameOffset[2] * self.ScaleFactor
		end
		if parse.optionalString("+Anchor:") then parse.getString() end
		if parse.optionalString("+Primary Inactive Offset:") then
			t.PrimaryInactiveOffset = parse.getFloat() * self.ScaleFactor
		end
		if parse.optionalString("+Secondary Inactive Offset:") then
			t.SecondaryInactiveOffset = parse.getFloat() * self.ScaleFactor
		end
		if parse.optionalString("+Name Offset:") then
			local off = NUi:GetCSV(parse.getString())
			t.NameOffset = { (tonumber(off[1]) or 10) * self.ScaleFactor, (tonumber(off[2]) or 0) * self.ScaleFactor }
		end
		if parse.optionalString("+Name Step:") then
			local step = NUi:GetCSV(parse.getString())
			t.NameStep = { (tonumber(step[1]) or 0) * self.ScaleFactor, (tonumber(step[2]) or 0) * self.ScaleFactor }
		end
		if parse.optionalString("+Ammo Offset:") then
			local off = NUi:GetCSV(parse.getString())
			t.AmmoOffsetX = (tonumber(off[1]) or 5) * self.ScaleFactor
			t.AmmoOffsetY = (tonumber(off[2]) or 0) * self.ScaleFactor
		end
		if parse.optionalString("+Font Scale:") then
			t.FontScale = parse.getFloat()
		end
		if parse.optionalString("+Show Names:") then
			t.ShowNames = parse.getString():lower() ~= "false"
		end
		if parse.optionalString("+Name Angle:") then
			t.NameAngleStep = parse.getFloat() * math.pi / 180
		end
		if parse.optionalString("+Divider Offset:") then
			local off = NUi:GetCSV(parse.getString())
			t.DividerOffset = { off[1] * self.ScaleFactor, off[2] * self.ScaleFactor }
		end
		if parse.optionalString("$Weapon Frames Colors:") then
			t.Colors.WeaponSlot = NUi:ParseColorBlock()
		end
		if parse.optionalString("$Divider Colors:") then
			t.Colors.Divider = NUi:ParseColorBlock()
		end
		if parse.optionalString("$Ammo Colors:") then
			local ammo = {}
			if parse.optionalString("+Good:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.Good = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Warning:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.Warning = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Bad:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.Bad = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Empty:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.Empty = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Out Of Ammo:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.OutOfAmmo = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Warning Inactive:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.WarningInactive = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			if parse.optionalString("+Bad Inactive:") then
				local rgba = NUi:GetCSV(parse.getString())
				ammo.BadInactive = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
			end
			t.Colors.Ammo = ammo
		end
		if parse.optionalString("$Cooldown Color:") then
			local rgba = NUi:GetCSV(parse.getString())
			t.Colors.Cooldown = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
		end
		if parse.optionalString("$Cooldown Inactive Color:") then
			local rgba = NUi:GetCSV(parse.getString())
			t.Colors.CooldownInactive = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
		end
		if parse.optionalString("$Debug Fake Weapons:") then
			NUiShipWeapons.DEBUG_FAKE_WEAPONS = parse.getString():lower() == "true"
		end
		if parse.optionalString("$Debug Primary Count:") then
			t.DebugPrimaryCount = math.min(math.max(math.floor(parse.getFloat()), 0), 3)
		else
			t.DebugPrimaryCount = 3
		end
		if parse.optionalString("$Debug Secondary Count:") then
			t.DebugSecondaryCount = math.min(math.max(math.floor(parse.getFloat()), 0), 3)
		else
			t.DebugSecondaryCount = 3
		end
	end
	t.NameOffset    = t.NameOffset or { 10 * self.ScaleFactor, 0 }
	t.NameStep      = t.NameStep   or { 0, 0 }
	t.AmmoOffsetX   = t.AmmoOffsetX or (5 * self.ScaleFactor)
	t.AmmoOffsetY   = t.AmmoOffsetY or 0
	t.FontScale     = (t.FontScale or 1.0) * self.ScaleFactor
	t.ShowNames     = t.ShowNames ~= false
	t.NameAngleStep = t.NameAngleStep or 0
	t.DividerOffset = t.DividerOffset or { 0, 0 }
	t.Colors.Ammo = t.Colors.Ammo or {}
	t.Colors.Ammo.Good      = t.Colors.Ammo.Good      or {255, 255, 255, 255}
	t.Colors.Ammo.Warning   = t.Colors.Ammo.Warning   or {240, 248,  16, 255}
	t.Colors.Ammo.Bad       = t.Colors.Ammo.Bad       or {241,  71,   9, 255}
	t.Colors.Ammo.Empty     = t.Colors.Ammo.Empty     or {255,   0,   0, 255}
	t.Colors.Ammo.OutOfAmmo      = t.Colors.Ammo.OutOfAmmo      or {120,   0,   0, 255}
	t.Colors.Ammo.WarningInactive = t.Colors.Ammo.WarningInactive or {120, 124,   8, 255}
	t.Colors.Ammo.BadInactive     = t.Colors.Ammo.BadInactive     or {120,  35,   5, 255}
	t.Colors.Cooldown         = t.Colors.Cooldown         or {241,  71,   9, 255}
	t.Colors.CooldownInactive = t.Colors.CooldownInactive or {160,  80,  30, 255}
	t.WeaponFramePosition = NUi:CalculatePosition(frameOrigin, frameOffset)

	t.Graphic.WeaponFrames = {}
	for i = 1, 6 do
		local name = "nui-weapons-frame" .. i
		t.Graphic.WeaponFrames[i] = {
			File   = name,
			Width  = gr.getImageWidth(name)  * self.ScaleFactor,
			Height = gr.getImageHeight(name) * self.ScaleFactor
		}
	end

	local dividerName = "nui-divider-weapon"
	t.Graphic.Divider = {
		File   = dividerName,
		Width  = gr.getImageWidth(dividerName)  * self.ScaleFactor,
		Height = gr.getImageHeight(dividerName) * self.ScaleFactor
	}

	t.Graphic.SplitDividers = {}
	for i = 1, 3 do
		local name = "nui-divider-weapon-" .. i .. "p"
		t.Graphic.SplitDividers[i] = {
			File   = name,
			Width  = gr.getImageWidth(name)  * self.ScaleFactor,
			Height = gr.getImageHeight(name) * self.ScaleFactor
		}
	end

	parse.requiredString("#End")
	self.WeaponsFrame = t
end

function NUiShipWeapons:SetupWeaponsFrame()
	mn.runSEXP("(hud-set-retail-gauge-active (false) !Weapons!)")
	self.BankStates = nil
	self.LastDrawTime = nil
	if self.NameTextures then
		for _, entry in pairs(self.NameTextures) do
			entry.tex:unload()
		end
	end
	self.NameTextures = {}
end

function NUiShipWeapons:LogWeaponBank(label, bank)
	if not (bank and bank:isValid()) then return end
	local wc = bank.WeaponClass
	NDebugger:log("weapons", string.format("%s %s | FireWait=%.2f CargoSize=%d BurstSeed=%d",
		label, wc.Name, wc.FireWait, wc.CargoSize, bank.BurstSeed))
end

function NUiShipWeapons:GetNameTexture(name)
	if self.NameTextures[name] then return self.NameTextures[name] end
	if not self.WeaponFont then return nil end

	gr.CurrentFont = self.WeaponFont
	local tw = gr.getStringWidth(name)
	local th = self.WeaponFont.Height
	local pad = th
	local texW = tw + pad * 2
	local texH = th + pad * 2

	local tex = gr.createTexture(texW, texH, TEXTURE_STATIC)
	gr.CurrentRenderTarget = tex
	gr.setColor(0, 0, 0, 255)
	gr.drawRectangle(0, 0, texW, texH, true)
	gr.setColor(255, 255, 255, 255)
	gr.CurrentFont = self.WeaponFont
	gr.drawString(name, pad, pad)
	gr.CurrentRenderTarget = nil
	tex:destroyRenderTarget()

	self.NameTextures[name] = { tex = tex, tw = tw, th = th, pad = pad }
	return self.NameTextures[name]
end

function NUiShipWeapons:ConfigWeaponOverheatBar()
	self.Active.WeaponOverheatBar = true

	local t = { Graphic = {}, Colors = {} }

	if parse.requiredString("$Frame Positioning:") then
		t.Graphic.Frame = NUi:ParseGraphicBlock(self.ScaleFactor)
	end

	if parse.optionalString("$Label Positioning:") then
		t.Graphic.Label = NUi:ParseGraphicBlock(self.ScaleFactor)
	end

	if parse.optionalString("$Glow Positioning:") then
		t.Graphic.Glow = NUi:ParseGraphicBlock(self.ScaleFactor)
		if parse.optionalString("+Threshold:") then
			t.Graphic.Glow.Threshold = parse.getFloat()
		else
			t.Graphic.Glow.Threshold = 0.9
		end
	end

	if parse.optionalString("$Bar Positioning:") then
		t.Graphic.Bar = NUi:ParseGraphicBlock(self.ScaleFactor)
		if parse.optionalString("+Label:") then
			t.Graphic.Bar.LabelImage = parse.getString()
		end
		if parse.optionalString("+Direction:") then
			t.Direction = NUi:GetDirection(parse.getString())
		else
			t.Direction = NUi.Direction.RIGHT
		end
	end

	if parse.optionalString("$Frame Colors:") then
		t.Colors.Frame = NUi:ParseColorBlock()
	else
		t.Colors.Frame = { Mode = "lerp", Colors = {{127, 127, 127, 255}}, Label = {0, 0, 0, 50} }
	end

	if parse.optionalString("$Bar Colors:") then
		t.Colors.Bar = NUi:ParseColorBlock()
	else
		t.Colors.Bar = { Mode = "lerp", Colors = {{127, 127, 127, 255}}, Label = {0, 0, 0, 50} }
	end

	parse.requiredString("#End")
	self.WeaponOverheatBar = t
end

function NUiShipWeapons:SetupWeaponOverheatBar()
	mn.runSEXP("(hud-set-retail-gauge-active (false) !Weapon energy!)")
	local t = self.WeaponOverheatBar
	t.Draw = NUiShipWeapons.DrawWeaponOverheatBar
end

function NUiShipWeapons:DrawWeaponOverheatBar()
	local barInfo = self.Graphic
	local energyLevel = hv.Player.WeaponEnergyLeft / hv.Player.WeaponEnergyMax
	local heatLevel = 1 - energyLevel
	local resolvedColor = NUi:ResolveThermalColor(self.Colors.Bar, heatLevel)

--- @type ElementInfo
	local frameElement = {
		Position = { x = barInfo.Frame.Position.x, y = barInfo.Frame.Position.y },
		Offset = { x = barInfo.Frame.Offset[1], y = barInfo.Frame.Offset[2] },
		Dimensions = { Width = barInfo.Frame.Width, Height = barInfo.Frame.Height },
		Image = barInfo.Frame.File,
		Color = NUi:ResolveColor(self.Colors.Frame, 1),
		Direction = self.Direction,
		Percentage = 1
	}

--- @type ElementInfo
	local frameLabelElement = {
		Position = { x = barInfo.Frame.Position.x, y = barInfo.Frame.Position.y },
		Offset = { x = barInfo.Frame.Offset[1], y = barInfo.Frame.Offset[2] },
		Dimensions = { Width = barInfo.Frame.LabelWidth or barInfo.Frame.Width, Height = barInfo.Frame.LabelHeight or barInfo.Frame.Height },
		Image = barInfo.Frame.LabelImage,
		Color = self.Colors.Frame.Label,
		Direction = self.Direction,
		Percentage = 1
	}

--- @type ElementInfo
	local barElement = {
		Position = { x = barInfo.Bar.Position.x, y = barInfo.Bar.Position.y },
		Offset = { x = barInfo.Bar.Offset[1], y = barInfo.Bar.Offset[2] },
		Dimensions = { Width = barInfo.Bar.Width, Height = barInfo.Bar.Height },
		Image = barInfo.Bar.File,
		Color = resolvedColor,
		Direction = self.Direction,
		Percentage = energyLevel,
		Inverse = barInfo.Bar.Inverse
	}

--- @type ElementInfo
	local barLabelElement = {
		Position = { x = barInfo.Bar.Position.x, y = barInfo.Bar.Position.y },
		Offset = { x = barInfo.Bar.Offset[1], y = barInfo.Bar.Offset[2] },
		Dimensions = { Width = barInfo.Bar.Width, Height = barInfo.Bar.Height },
		Image = barInfo.Bar.LabelImage,
		Color = resolvedColor,
		Direction = self.Direction,
		Percentage = energyLevel
	}

	if barInfo.Label then
--- @type ElementInfo
		local labelElement = {
			Position = { x = barInfo.Label.Position.x, y = barInfo.Label.Position.y },
			Offset = { x = barInfo.Label.Offset[1], y = barInfo.Label.Offset[2] },
			Dimensions = { Width = barInfo.Label.Width, Height = barInfo.Label.Height },
			Image = barInfo.Label.File,
			Color = resolvedColor,
			Direction = self.Direction,
			Percentage = 1
		}
		NUi:DrawHudElement(labelElement)
	end

	NUi:DrawHudElement(frameElement)
	NUi:DrawHudElement(frameLabelElement)

	if barInfo.Glow then
		local glowThreshold = barInfo.Glow.Threshold
		local glowAlpha = math.floor(math.max(0, (heatLevel - glowThreshold) / (1 - glowThreshold)) * 255)
		if glowAlpha > 0 then
--- @type ElementInfo
			local glowElement = {
				Position = { x = barInfo.Glow.Position.x, y = barInfo.Glow.Position.y },
				Offset = { x = barInfo.Glow.Offset[1], y = barInfo.Glow.Offset[2] },
				Dimensions = { Width = barInfo.Glow.Width, Height = barInfo.Glow.Height },
				Image = barInfo.Glow.File,
				Color = { resolvedColor[1], resolvedColor[2], resolvedColor[3], glowAlpha },
				Direction = self.Direction,
				Percentage = 1
			}
			NUi:DrawHudElement(glowElement)
		end
	end

	NUi:DrawHudElement(barElement)
	NUi:DrawHudElement(barLabelElement)
end

function NUiShipWeapons:DrawWeaponNames()
	if not self.WeaponFont then
		for i = 1, #gr.Fonts do
			local f = gr.Fonts[i]
			if f.Name == "CommChatWeapon" then
				self.WeaponFont = f
				break
			end
		end
	end

	if self.WeaponFont then
		gr.CurrentFont = self.WeaponFont
	end

	local now = mn.getMissionTime()
	local dt = math.min(now - (self.LastDrawTime or now), 0.1)
	self.LastDrawTime = now

	local plyr = hv.Player

	local wf = self.WeaponsFrame
	local numP, numS, primaryBanks, secondaryBanks

	if NUiShipWeapons.DEBUG_FAKE_WEAPONS then
		numP = wf.DebugPrimaryCount   or 3
		numS = wf.DebugSecondaryCount or 3
		local function fb(name, armed, ammoLeft, ammoMax, cargoSize, fireWait)
			return { WeaponClass = { Name = name, FireWait = fireWait or 0.1, CargoSize = cargoSize or 0 }, Armed = armed, BurstSeed = 0, AmmoLeft = ammoLeft, AmmoMax = ammoMax, isValid = function() return true end }
		end
		primaryBanks = {
			fb("Old Pond",    true,  0, 0),
			fb("Silent Frog", false, 0, 0),
			fb("Autumn Dusk", false, 0, 0),
			Linked = false,
		}
		secondaryBanks = {
			fb("Cherry Seeker", true,  8, 20, 1, 2.0),
			fb("Wind Blossom",  false, 3, 20, 1, 2.0),
			fb("Moon Drop",     false, 0, 20, 1, 2.0),
			DualFire = false,
		}
	else
		numP          = plyr.Class.numPrimaryBanks
		numS          = plyr.Class.numSecondaryBanks
		primaryBanks   = plyr.PrimaryBanks
		secondaryBanks = plyr.SecondaryBanks
	end

	if numP + numS == 0 then return end

	if not self.BankStates then
		self.BankStates = { Primary = {}, Secondary = {} }
		for i = 1, numP do
			local bank = primaryBanks[i]
			local armed = bank and bank:isValid() and bank.Armed or false
			self.BankStates.Primary[i] = {
				XOffset       = armed and 0 or wf.PrimaryInactiveOffset,
				ColorT        = armed and 1.0 or 0.0,
				LastFireTime  = 0,
				LastBurstSeed = bank and bank.BurstSeed or -1
			}
		end
		for i = 1, numS do
			local bank = secondaryBanks[i]
			local armed = bank and bank:isValid() and bank.Armed or false
			self.BankStates.Secondary[i] = {
				XOffset       = armed and 0 or wf.SecondaryInactiveOffset,
				ColorT        = armed and 1.0 or 0.0,
				LastFireTime  = 0,
				LastBurstSeed = bank and bank.BurstSeed or -1
			}
		end
	end

	local lerpSpeed = 8
	local t = math.min(1, lerpSpeed * dt)
	local totalWeapons = math.min(numP + numS, 6)
	local framePos = wf.WeaponFramePosition
	local frameInfo = wf.Graphic.WeaponFrames[totalWeapons]
	NUiShipWeapons.WeaponPanelBottomY = framePos.y + frameInfo.Height


--- draw combined weapon frame
--- @type ElementInfo
	local weaponFrameElement = {
		Position = { x = framePos.x - frameInfo.Width, y = framePos.y },
		Offset = { x = 0, y = 0 },
		Dimensions = { Width = frameInfo.Width, Height = frameInfo.Height },
		Image = frameInfo.File,
		Color = NUi:ResolveColor(wf.Colors.WeaponSlot, 1),
		Direction = NUi.Direction.RIGHT,
		Percentage = 1
	}
	NUi:DrawHudElement(weaponFrameElement)

--- draw divider: split version if both types present, plain otherwise
	local divInfo = (numP > 0 and numS > 0) and wf.Graphic.SplitDividers[math.min(numP, 3)] or wf.Graphic.Divider
--- @type ElementInfo
	local dividerElement = {
		Position = { x = framePos.x - divInfo.Width + wf.DividerOffset[1], y = framePos.y + wf.DividerOffset[2] },
		Offset = { x = 0, y = 0 },
		Dimensions = { Width = divInfo.Width, Height = divInfo.Height },
		Image = divInfo.File,
		Color = NUi:ResolveColor(wf.Colors.Divider, 1),
		Direction = NUi.Direction.RIGHT,
		Percentage = 1
	}
	NUi:DrawHudElement(dividerElement)

	if not wf.ShowNames then return end

--- draw primary weapon names and ammo
	local primaryLinked = primaryBanks.Linked
	local frameLeft = framePos.x - frameInfo.Width
	local fs = wf.FontScale
	for i = 1, numP do
		local state = self.BankStates.Primary[i]
		local bank = primaryBanks[i]
		local active = (bank and bank:isValid() and bank.Armed) or primaryLinked
		local targetX = active and 0 or wf.PrimaryInactiveOffset
		local targetC = active and 1.0 or 0.0
		state.XOffset = state.XOffset + (targetX - state.XOffset) * t
		state.ColorT  = state.ColorT  + (targetC  - state.ColorT)  * t
		local c = math.floor(150 + 105 * state.ColorT)
		gr.setColor(c, c, c, 255)
		local slotIndex = i - 1
		local baseX = frameLeft + wf.NameOffset[1] + wf.NameStep[1] * slotIndex
		local baseY = wf.NameOffset[2] + wf.NameStep[2] * slotIndex
		local rowAngle = wf.NameAngleStep
		local wc = bank and bank.WeaponClass
		local hasPhysicalAmmo = wc ~= nil and wc.CargoSize > 0
		if bank and bank:isValid() then
			local seed = bank.BurstSeed
			if seed ~= state.LastBurstSeed then
				state.LastFireTime = now
				state.LastBurstSeed = seed
			end
		end
		local cooldownRemaining = 0
		if wc and state.LastFireTime > 0 and wc.FireWait >= 1.0 then
			cooldownRemaining = math.max(0, wc.FireWait - (now - state.LastFireTime))
		end
		local weaponName = wc and wc.Name or ""
		local displayName = weaponName
		if cooldownRemaining > 0.05 then
			displayName = weaponName .. " (" .. math.ceil(cooldownRemaining) .. ")"
		end
		local ne = self:GetNameTexture(displayName)
		if ne then
			local sw, sh, sp = ne.tw * fs, ne.th * fs, ne.pad * fs
			local dx = baseX + state.XOffset
			local textY = framePos.y + baseY
			local nameColor
			if hasPhysicalAmmo and bank.AmmoLeft == 0 then
				nameColor = wf.Colors.Ammo.OutOfAmmo
			elseif cooldownRemaining > 0.05 then
				nameColor = active and wf.Colors.Cooldown or wf.Colors.CooldownInactive
			else
				nameColor = {c, c, c, 255}
			end
			gr.setColor(nameColor[1], nameColor[2], nameColor[3], nameColor[4])
			gr.drawImage(ne.tex, dx - sp, textY - sp, dx + sw + sp, textY + sh + sp, 0, 0, 1, 1, 1, true, rowAngle)
		end
		if bank then
			local ammoStr
			if hasPhysicalAmmo and bank.AmmoMax < 10000 then
				ammoStr = tostring(bank.AmmoLeft)
			end
			if ammoStr then
				local ae = self:GetNameTexture(ammoStr)
				if ae then
					local aw, ah, ap = ae.tw * fs, ae.th * fs, ae.pad * fs
					local ax = framePos.x - wf.AmmoOffsetX - aw
					local ay = framePos.y + baseY + wf.AmmoOffsetY
					local ammoRatio = bank.AmmoLeft / bank.AmmoMax
					local ammoColor
					if bank.AmmoLeft == 0 then ammoColor = wf.Colors.Ammo.Empty
					elseif ammoRatio <= 0.15 then ammoColor = active and wf.Colors.Ammo.Bad or wf.Colors.Ammo.BadInactive
					elseif ammoRatio <= 0.33 then ammoColor = active and wf.Colors.Ammo.Warning or wf.Colors.Ammo.WarningInactive
					else ammoColor = active and wf.Colors.Ammo.Good or {c, c, c, 255} end
					gr.setColor(ammoColor[1], ammoColor[2], ammoColor[3], ammoColor[4])
					gr.drawImage(ae.tex, ax - ap, ay - ap, ax + aw + ap, ay + ah + ap, 0, 0, 1, 1, 1, true, rowAngle)
				end
			end
		end
	end

--- draw secondary weapon names and ammo
	local secondaryDualFire = secondaryBanks.DualFire
	for i = 1, numS do
		local state = self.BankStates.Secondary[i]
		local bank = secondaryBanks[i]
		local active = (bank and bank:isValid() and bank.Armed) or secondaryDualFire
		local targetX = active and 0 or wf.SecondaryInactiveOffset
		local targetC = active and 1.0 or 0.0
		state.XOffset = state.XOffset + (targetX - state.XOffset) * t
		state.ColorT  = state.ColorT  + (targetC  - state.ColorT)  * t
		local c = math.floor(150 + 105 * state.ColorT)
		gr.setColor(c, c, c, 255)
		local slotIndex = numP + i - 1
		local baseX = frameLeft + wf.NameOffset[1] + wf.NameStep[1] * slotIndex
		local baseY = wf.NameOffset[2] + wf.NameStep[2] * slotIndex
		local rowAngle = wf.NameAngleStep
		local wcS = bank and bank.WeaponClass
		local hasPhysicalAmmoS = wcS ~= nil and wcS.CargoSize > 0
		if bank and bank:isValid() then
			local seedS = bank.BurstSeed
			if seedS ~= state.LastBurstSeed then
				state.LastFireTime = now
				state.LastBurstSeed = seedS
			end
		end
		local cooldownRemainingS = 0
		if wcS and state.LastFireTime > 0 and wcS.FireWait >= 1.0 then
			cooldownRemainingS = math.max(0, wcS.FireWait - (now - state.LastFireTime))
		end
		local weaponNameS = wcS and wcS.Name or ""
		local displayNameS = weaponNameS
		if cooldownRemainingS > 0.05 then
			displayNameS = weaponNameS .. " (" .. math.ceil(cooldownRemainingS) .. ")"
		end
		local ne = self:GetNameTexture(displayNameS)
		if ne then
			local sw, sh, sp = ne.tw * fs, ne.th * fs, ne.pad * fs
			local dx = baseX + state.XOffset
			local textY = framePos.y + baseY
			local nameColorS
			if hasPhysicalAmmoS and bank.AmmoLeft == 0 then
				nameColorS = wf.Colors.Ammo.OutOfAmmo
			elseif cooldownRemainingS > 0.05 then
				nameColorS = active and wf.Colors.Cooldown or wf.Colors.CooldownInactive
			else
				nameColorS = {c, c, c, 255}
			end
			gr.setColor(nameColorS[1], nameColorS[2], nameColorS[3], nameColorS[4])
			gr.drawImage(ne.tex, dx - sp, textY - sp, dx + sw + sp, textY + sh + sp, 0, 0, 1, 1, 1, true, rowAngle)
		end
		if hasPhysicalAmmoS and bank.AmmoMax < 10000 then
			local ammoStrS = tostring(bank.AmmoLeft)
			local ae = self:GetNameTexture(ammoStrS)
			if ae then
				local aw, ah, ap = ae.tw * fs, ae.th * fs, ae.pad * fs
				local ax = framePos.x - wf.AmmoOffsetX - aw
				local ay = framePos.y + baseY + wf.AmmoOffsetY
				local ammoRatioS = bank.AmmoLeft / bank.AmmoMax
				local ammoColorS
				if bank.AmmoLeft == 0 then ammoColorS = wf.Colors.Ammo.Empty
				elseif ammoRatioS <= 0.15 then ammoColorS = active and wf.Colors.Ammo.Bad or wf.Colors.Ammo.BadInactive
				elseif ammoRatioS <= 0.33 then ammoColorS = active and wf.Colors.Ammo.Warning or wf.Colors.Ammo.WarningInactive
				else ammoColorS = active and wf.Colors.Ammo.Good or {c, c, c, 255} end
				gr.setColor(ammoColorS[1], ammoColorS[2], ammoColorS[3], ammoColorS[4])
				gr.drawImage(ae.tex, ax - ap, ay - ap, ax + aw + ap, ay + ah + ap, 0, 0, 1, 1, 1, true, rowAngle)
			end
		end
	end
end

function NUiShipWeapons:Draw()
	if hv.Player.HitpointsLeft > 0 then

		local plyrClass = hv.Player.Class
		if NUiShipWeapons.DEBUG_FAKE_WEAPONS or plyrClass.numPrimaryBanks + plyrClass.numSecondaryBanks > 0 then
			self:DrawWeaponNames()
			if self.Active.WeaponOverheatBar then self.WeaponOverheatBar:Draw() end
		end
	end
end

