ExtraButtons_PREFIX = "DarkUIExtraButtons"
ExtraButtons =
{ 
	[1]	= 	
		{
			name	= "MainLeft",
			parent	= MainMenuBarArtFrame,
			pos 	= {"TOPRIGHT", ActionButton1, "TOPLEFT", -9, 8}
		},
	[2]	=	
		{
			name	= "MainRight",
			parent 	= MainMenuBarArtFrame,
			pos		= {"TOPLEFT", ActionButton12, "TOPRIGHT", 12, 8}
		}, 
	[3]	=	
		{
			name	= "TopLeft",
			parent 	= MultiBarBottomLeft,
			pos 	= {"TOPRIGHT", MultiBarBottomRightButton1, "TOPLEFT", -35, -39}
		},
	[4]	=	
		{
			name	= "TopRight",
			parent	= MultiBarBottomLeft,
			pos		= {"TOPLEFT", MultiBarBottomRightButton12, "TOPRIGHT", 35, -39}
		}
}

local function Button_OnEnter(self)
	ActionButton_SetTooltip(self)
end

local function Button_OnLeave(self)
	GameTooltip:Hide()
end

--[[ Create ]]
local Extra = CreateFrame("Frame", nil, UIParent, "SecureFrameTemplate")
Extra:RegisterEvent("PLAYER_LOGIN")
Extra.buttons = {}

function Extra:CreateButton(index, config)
	local name = ExtraButtons_PREFIX..config.name

	local bar = CreateFrame("Frame", name.."Bar", config.parent, "SecureHandlerStateTemplate")
	bar:SetAttribute("actionpage", 11 - index)
	bar:SetFrameStrata("LOW")
	bar:SetSize(54, 54)
	bar:SetID(index)
	bar:SetPoint(unpack(config.pos))

	local button = CreateFrame("CheckButton", name.."BarButton", bar, "ActionBarButtonTemplate")

	button:SetID(0)
	button:SetAllPoints()
	button:SetScript("OnEnter", Button_OnEnter)
	button:SetScript("OnLeave", Button_OnLeave)
	button:SetAttribute("action", 108 + index)
	
	Extra.buttons[name] = button
end

function Extra:Init()
	for index, config in pairs(ExtraButtons) do
		Extra:CreateButton(index, config)
	end

	local cvar = GetCVar("alwaysShowActionBars") or "0"
	Extra.showgrid = tonumber(cvar)

    -- add events for grid, must after bars initial
    self:RegisterEvent("ACTIONBAR_SHOWGRID")
    self:RegisterEvent("ACTIONBAR_HIDEGRID")
    self:RegisterEvent("PLAYER_ENTERING_WORLD")
    -- hooks for grid
    hooksecurefunc("MultiActionBar_ShowAllGrids",function()
        Extra.showgrid = 1
        Extra:UpdateGrid()
    end)
    hooksecurefunc("MultiActionBar_HideAllGrids",function()
        Extra.showgrid = 0
        Extra:UpdateGrid()
    end)
end

function Extra:OnEvent(event, ...)
    if event == "PLAYER_LOGIN" then
        -- self init
        self:Init()
      
        -- init AfterCombat Events
        self:InitAfterCombat()
    elseif event == "PLAYER_REGEN_ENABLED" then
        if InCombatLockdown() then
        else
            self:CallAfterCombat()
        end
    else
        self:OnUpdateGridEvent(event)
    end
end

Extra:SetScript("OnEvent", Extra.OnEvent)

function Extra:OnUpdateGridEvent(event, ...)
	-- event stuff
	if event == "ACTIONBAR_SHOWGRID" then
		Extra.showgrid = 1
	elseif event == "ACTIONBAR_HIDEGRID" then
		Extra.showgrid = 0
	else
		self:SafeCallFunc(self.UpdateGrid)
	end
end

function Extra:UpdateGrid()
	-- in combat we can't let it be shown or hidden
	if InCombatLockdown() then return end

	if GetCVar("alwaysShowActionBars") == "1" then Extra.showgrid = 1 end

	for _, button in pairs(Extra.buttons) do
		button:SetAttribute("showgrid", Extra.showgrid)

		if Extra.showgrid > 0 then
			if not button:GetAttribute("statehidden") then
				button:Show()
				_G[button:GetName().."NormalTexture"]:SetVertexColor(1.0, 1.0, 1.0, 0.5)
			end
		elseif not HasAction(button.action) then
			button:Hide()
		end
	end
end

Extra.AfterCombatCallList = {}

function Extra:InitAfterCombat()
    self:RegisterEvent("PLAYER_REGEN_ENABLED")
end

function Extra:RegisterSafeCallObj(func, ...)
  --self.AfterCombatCallList[tostring(func)] = {func, {...}}
  table.insert(self.AfterCombatCallList, {func, {...}})
end

function Extra:SafeCallFunc(func, ...)
  assert(type(func) == 'function', 
    'Wrong param for Extra.SafeCallFunc, need a function type, got ' .. type(func))
    
    if InCombatLockdown() then
        Extra:RegisterSafeCallObj(func, ...)
    else
      func(...)
    end
end

function Extra:CallAfterCombat()
    local index, pack
    for index, pack in pairs(self.AfterCombatCallList) do
        pack[1](unpack(pack[2]))
    end

    table.wipe(self.AfterCombatCallList)
end