---------------------------------------------------------------
local db = ConsolePort:GetData()
---------------------------------------------------------------
local addOn, ab = ...
---------------------------------------------------------------
local cfg

local Bar = CreateFrame('Frame', addOn, UIParent, 'SecureHandlerStateTemplate, SecureHandlerShowHideTemplate')
local WrapperLib = ab.libs.wrapper
local state, now = ConsolePort:GetActionPageDriver()

local BAR_MIN_WIDTH = 1105
local BAR_MAX_SCALE = 1.6
local BAR_FIXED_HEIGHT = 140
local BUTTON_LAYOUT

-- Set up action bar
---------------------------------------------------------------
ab.bar = Bar
ab.data = db
---------------------------------------------------------------

Bar:SetAttribute('actionpage', now)
Bar:SetFrameRef('ActionBar', MainMenuBarArtFrame)
Bar:SetFrameRef('OverrideBar', OverrideActionBar)
Bar:SetFrameRef('Cursor', ConsolePortRaidCursor)
Bar:SetFrameRef('Mouse', ConsolePortMouseHandle)

Bar:Execute([[
	bindings = newtable()
	bar = self
	cursor = self:GetFrameRef('Cursor')
	mouse = self:GetFrameRef('Mouse')
	self:SetAttribute('state', '')
]])

function Bar:FadeIn()
	db.UIFrameFadeIn(self, 1, 0, 1)
end

function Bar:UnregisterOverrides()
	self:Execute([[
		bindings = wipe(bindings)
		self:ClearBindings()
	]])
end

function Bar:UpdateOverrides()
	self:Execute([[
		for key, button in pairs(bindings) do
			self:SetBindingClick(true, key, button)
		end
	]])
end

function Bar:RegisterOverride(key, button)
	self:Execute(format([[
		bindings['%s'] = '%s'
	]], key, button))
end

function Bar:OnNewBindings(...)
	if not InCombatLockdown() then
		self:UnregisterOverrides()
		WrapperLib:UpdateAllBindings(...)
		self:UpdateOverrides()
	end
end

ConsolePort:RegisterCallback('OnNewBindings', Bar.OnNewBindings, Bar)

function Bar:OnEvent(event, ...)
	if self[event] then
		self[event](self, ...)
	end
end

function Bar:ADDON_LOADED(...)
	local name = ...
	if name == addOn then
		if not ConsolePortBarSetup then
			ConsolePortBarSetup = {
				scale = 0.9,
				width = BAR_MIN_WIDTH,
				watchbars = true,
				showline = true,
				lock = true,
			}
		end
		self:OnLoad(ConsolePortBarSetup)
		self:UnregisterEvent('ADDON_LOADED')
	end
end

function Bar:OnMouseWheel(delta)
	if not InCombatLockdown() then
		local cfg = ab.cfg
		if IsShiftKeyDown() then
			local newWidth = self:GetWidth() + ( delta * 10 )
			cfg.width = newWidth > BAR_MIN_WIDTH and newWidth or BAR_MIN_WIDTH
			self:SetWidth(cfg.width)
		else
			local newScale = self:GetScale() + ( delta * 0.1 )
			if newScale > BAR_MAX_SCALE then cfg.scale = BAR_MAX_SCALE
			elseif newScale <= 0 then cfg.scale = 0.1
			else cfg.scale = newScale end
			self:SetScale(cfg.scale)
		end
	end
end

function Bar:OnLoad(cfg, benign)
	ab.cfg = cfg
	ConsolePortBarSetup = cfg
	self:SetScale(cfg.scale or 1)

	-- Set action bar art
	if cfg.showart then
		local art, coords = ab:GetCover()
		if art and coords then
			self.CoverArt:SetTexture(art)
			self.CoverArt:SetTexCoord(unpack(coords))
			self.CoverArt:Show()
		end
	else
		self.CoverArt:Hide()
	end

	-- Show class tint line
	if cfg.showline then
		self.BG:Show()
		self.BottomLine:Show()
	else
		self.BG:Hide()
		self.BottomLine:Hide()
	end

	-- Always show modifiers
	if cfg.showbuttons then
		self.Eye:SetAttribute('showbuttons', true)
		self:Execute([[
			control:ChildUpdate('hover', true)
		]])
	else
		self.Eye:SetAttribute('showbuttons', false)
		self:Execute([[
			control:ChildUpdate('hover', false)
		]])
	end

	-- Show quick menu buttons
	self.Menu:SetShown(cfg.quickMenu)

	if cfg.lockpet then
		self.Pet:RegisterForDrag()
	else
		self.Pet:RegisterForDrag('LeftButton')
	end

	if cfg.lock then
		self:RegisterForDrag()
		self:EnableMouse(false)
	else
		self:EnableMouse(true)
		self:RegisterForDrag('LeftButton')
	end

	self:EnableMouseWheel(cfg.mousewheel)

	cfg.layout = cfg.layout or ab:GetDefaultButtonLayout()

	local layout = cfg.layout
	for binding in ConsolePort:GetBindings() do
		local position = layout[binding]
		local wrapper = WrapperLib:Get(binding) or WrapperLib:Create(self, binding, position and position.dir)

		if position then
			wrapper:SetPoint(unpack(position.point))
			if position.size then
				wrapper:SetSize(position.size)
			end
		else
			wrapper:Hide()
		end
		self.Buttons[#self.Buttons + 1] = wrapper
	end

	-- Don't run this when updating simple cvars
	if not benign then
		WrapperLib:UpdateAllBindings()
		self:Hide()
		self:Show()

		self:SetAttribute('page', 1)
		self:Execute(format([[
			control:ChildUpdate('state', '')
			self:RunAttribute('_onstate-page', '%s')
		]], now or 1))
	end

	self.WatchBarContainer:Hide()
	self.WatchBarContainer:Show()

	local width = cfg.width or ( #self.Buttons > 10 and (10 * 110) + 55 or (#self.Buttons * 110) + 55 )
	self:SetSize(width, BAR_FIXED_HEIGHT)
end

--------------------------
---- Secure functions ----
--------------------------

for name, script in pairs({
	['_onhide'] = [[
		self:ClearBindings()
	]],
	['_onshow'] = [[
		for key, button in pairs(bindings) do
			self:SetBindingClick(true, key, button)
		end
		mouse:RunAttribute('UpdateTarget', mouse:GetAttribute('current'))
		self:CallMethod('FadeIn')
	]],
	['_onstate-modifier'] = [[
		self:SetAttribute('state', newstate)
		control:ChildUpdate('state', newstate)
		cursor:RunAttribute('pageupdate')
	]],
	['_onstate-page'] = [[
		if HasVehicleActionBar() then
			newstate = GetVehicleBarIndex()
		elseif HasOverrideActionBar() then
			newstate = GetOverrideBarIndex()
		elseif HasTempShapeshiftActionBar() then
			newstate = GetTempShapeshiftBarIndex()
		elseif GetBonusBarOffset() > 0 then
			newstate = GetBonusBarOffset()+6
		else
			newstate = GetActionBarPage()
		end
		self:SetAttribute('actionpage', newstate)
		control:ChildUpdate('actionpage', newstate)
	]]
}) do Bar:SetAttribute(name, script) end

--------------------------

Bar:SetScript('OnEvent', Bar.OnEvent)
Bar:SetScript('OnMouseWheel', Bar.OnMouseWheel)
Bar:RegisterEvent('PLAYER_LOGIN')
Bar:RegisterEvent('ADDON_LOADED')
Bar:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
Bar:RegisterEvent('PLAYER_TALENT_UPDATE')

Bar.ignoreNode = true
Bar.Buttons = {}
Bar.Elements = {}
Bar.isForbidden = true
Bar:SetClampedToScreen(true)
Bar:SetMovable(true)
Bar:SetScript('OnDragStart', Bar.StartMoving)
Bar:SetScript('OnDragStop', Bar.StopMovingOrSizing)
Bar:SetPoint('BOTTOM', UIParent, 0, 0)
RegisterStateDriver(Bar, 'page', state)
RegisterStateDriver(Bar, 'modifier', '[mod:ctrl,mod:shift] CTRL-SHIFT-; [mod:ctrl] CTRL-; [mod:shift] SHIFT-; ')
RegisterStateDriver(Bar, 'visibility', '[petbattle][vehicleui][overridebar] hide; show')