BossBar = {}

function BossBar:Init()
	require("nui-hud")
	self.Enabled = true		-- Is this thing on?
	self.Boss = nil				-- The boss ship handle
	self.Color = {0,0,0,0}		-- The color of the boss bar, we'll take the IFF color info from the boss
	self.LastHealth = 0			-- The health we'll compare to to see if it changed
	self.Health = 0				-- The current health
	self.TimeStart = 0			-- Time start for the easing function
	self.Changed = false		-- Notice if the health has changed
	self.ScreenWidth = gr.getScreenWidth() 		-- Duh
	self.ScreenHeight = gr.getScreenHeight() 	-- Super duh
	self.Alpha = 192 							--(set from 0-255, adjusts the transparency of the bar)
	
    self:ParseConfig("nui-hud.tbl")

	--Boss Bar coordinates, the border will draw a bit bigger than this though
	--self.Frame={File=filename,X=number,Y=number,Alpha=192}
	--self.Frame.Width = gr.getImageWidth(self.Frame.File)
	--self.Frame.Height = gr.getImageHeight(self.Frame.File)
	--If you want a frame (instead of an automatically drawn border), uncomment the 3 lines above and fill in file, x and y.
	--You can make self.Box's position get tied to the Frame's position by using self.Frame.x and self.Frame.y adding or subtracting a few pixels
	
	--self.Box={x1 = self.ScreenWidth*0.05, x2 = self.ScreenWidth*0.95, y1 = 20, y2 = 30} --This is a horizontal preset
	self.Box={y1 = self.ScreenHeight*0.25, y2 = self.ScreenHeight*0.75, x1 = 20, x2 = 50} --This is a vertical preset
	
	--self.BarGraphic = "healthbar"		--Uncomment this is you want a graphical bar
	self.Vertical = true				--Make this true if you want a vertical bar
	--self.ShowBossName = true			--If you want to see the boss's name near the boss bar
	
	if self.Vertical then
		self.FullBarWidth = self.Box.y2 - self.Box.y1
	else
		self.FullBarWidth = self.Box.x2 - self.Box.x1
	end
	
	if NDebugger then NDebugger:log("bossbar", "loaded") end

end

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

	NUi:ParseConfigSection(file, "#Boss Bar Settings", function() self:ConfigBossHealthBar() end)
end

function BossBar:ConfigBossHealthBar()
	local t = { Graphic = {}, Colors = {} }

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

		if parse.optionalString("+Label:") then
			t.Graphic.Frame.LabelImage = parse.getString()
		end

		if parse.optionalString("+Label Outline:") then
			t.Graphic.Frame.LabelOutlineImage = parse.getString()
		end
	end

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

		if parse.optionalString("+Direction:") then
			t.Direction = NUi:GetDirection(parse.getString())
		else
			t.Direction = NUi.Direction.RIGHT
		end

		if parse.optionalString("+Init Anim Time:") then
			t.Graphic.Bar.InitAnimTime = parse.getFloat()
		else
			t.Graphic.Bar.InitAnimTime = t.Graphic.Bar.AnimTime
		end
	end

	if parse.optionalString("$Frame Colors:") then
		t.Colors.Frame = NUi:ParseColorBlock()
		if parse.optionalString("+Label Outline:") then
			local rgba = NUi:GetCSV(parse.getString())
			t.Colors.Frame.LabelOutline = {rgba[1], rgba[2], rgba[3], rgba[4] or 255}
		else
			t.Colors.Frame.LabelOutline = {255, 255, 255, 255}
		end
	end

	if parse.optionalString("$Bar Colors:") then
		t.Colors.Bar = NUi:ParseColorBlock()
	end

	parse.requiredString("#End")

	BossBar.BossBarConfig = t
end

function BossBar:DrawBar(CurrentTime)
	local barInfo = self.BossBarConfig.Graphic
	local direction = self.BossBarConfig.Direction
	local frameAmount = 1
	local barAmount = BossBar:ChangeBarWidth(CurrentTime)

	local slideOffset = 0
	if self.SlideStartTime then
		local elapsed = CurrentTime - self.SlideStartTime
		local duration = barInfo.Frame.AnimTime
		local progress = NUi:EaseOut(elapsed / duration)
		slideOffset = (progress - 1) * barInfo.Frame.Width
	end

--- @type ElementInfo
	local frameElement = {
		Position = { x = barInfo.Frame.Position.x + slideOffset, 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.BossBarConfig.Colors.Frame, 1),
		Direction = direction,
		Percentage = frameAmount
	}

--- @type ElementInfo
	local frameLabelOutlineElement = {
		Position = { x = barInfo.Frame.Position.x + slideOffset, 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.LabelOutlineImage,
		Color = self.BossBarConfig.Colors.Frame.LabelOutline,
		Direction = direction,
		Percentage = frameAmount
	}

--- @type ElementInfo
	local frameLabelElement = {
		Position = { x = barInfo.Frame.Position.x + slideOffset, 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.LabelImage,
		Color = self.BossBarConfig.Colors.Frame.Label,
		Direction = direction,
		Percentage = frameAmount
	}

--- @type ElementInfo
	local barBackgroundElement = {
		Position = { x = barInfo.Bar.Position.x + slideOffset, 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 = self.BossBarConfig.Colors.Bar.Background,
		Direction = direction,
		Percentage = 1
	}

--- @type ElementInfo
	local barElement = {
		Position = { x = barInfo.Bar.Position.x + slideOffset, 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 = self.BossBarConfig.Colors.Bar.Good,
		Direction = direction,
		Percentage = barAmount
	}

	NUi:DrawHudElement(frameElement)
	NUi:DrawHudElement(frameLabelOutlineElement)
	NUi:DrawHudElement(frameLabelElement)
	NUi:DrawHudElement(barBackgroundElement)
	NUi:DrawHudElement(barElement)
end
	
function BossBar:UpdateHealth()
	if self.Enabled == true then
		if self.Boss ~= nil then
			if self.Health ~= self.Boss.HitpointsLeft/self.Boss.HitpointsMax then
				if self.Changed == false then
					self.Changed = true
					self.LastHealth = self.Health
					self.Health = self.Boss.HitpointsLeft/self.Boss.HitpointsMax
					self.TimeStart = mn.getMissionTime()
					if self.SlideStartTime then
						local slideEnd = self.SlideStartTime + self.BossBarConfig.Graphic.Frame.AnimTime
						if self.TimeStart < slideEnd then
							self.TimeStart = slideEnd
						end
					end
					--ba.print("HEALTH CHANGED!!!\n")
				end
			end
		end
	end
	
end

function BossBar:ChangeBarWidth(CurrentTime)

	-- returns from 0 to 1.0 the width the health bar should be, uses an easing function to help make it move smoothly

	local beginval = self.LastHealth
	local endval = self.Health
	local change = endval - beginval
	local duration = self.InitialFill and self.BossBarConfig.Graphic.Bar.InitAnimTime or self.BossBarConfig.Graphic.Bar.AnimTime
	local easeTime = math.max(0, CurrentTime - self.TimeStart)

	local result = self.Health

	if self.Changed == true then
		result = NUi:Ease(easeTime, beginval, change, duration)
	end

	if ((endval > beginval) and (result >= endval)) or ((endval < beginval) and (result <= endval)) then
		result = endval
		self.Changed = false
		self.InitialFill = false
	end
	
	if result < 0 and self.Boss:hasShipExploded() then
		result = 0
	end

	return result

end

function BossBar:Activate(boss)
	if not BossBar.Enabled then
        BossBar:Init()
    end

    BossBar.Boss = boss
    local r,g,b = BossBar.Boss.Team:getColor()
    BossBar.Color[1] = r
    BossBar.Color[2] = g
    BossBar.Color[3] = b
    BossBar.Color[4] = self.Alpha
    BossBar.InitialFill = true
    BossBar.SlideStartTime = mn.getMissionTime()
end

function BossBar:Exit()
	self.Enabled = nil
	self.Boss = nil
	self.Color = nil
	self.LastHealth = nil
	self.Health = nil
	self.TimeStart = nil
	self.Changed = nil
	self.InitialFill = nil
	self.SlideStartTime = nil
	self.ScreenWidth = nil
	self.ScreenHeight = nil
	--self.Ease = nil
	self.Box = nil
	self.FullBarWidth = nil
end
			
function bossBarOn(ship)
	if mn.Ships[ship]:isValid() then
		BossBar:Activate(ship)
	end
end

function bossBarOff()
	if BossBar.Enabled then
		BossBar:Exit()
	end
end