local addon, ns = ...
local cfg = ns.cfg
local mAB = CreateFrame("Frame")

---- Addon functions
local myclass = select(2, UnitClass("player"))
local null = function() end

-- holder creating func
local CreateHolder = function(name, pos)
	local bar = CreateFrame("Frame", name, UIParent, "SecureHandlerStateTemplate")
	bar:SetPoint(pos.a, pos.x, pos.y)
	return bar
end 

-- styling totembar
if not cfg.config_totembar then	cfg.config_totembar = {cfg.totembar_enable_timers, 32, 8, false, cfg.totembar_alpha} end -- temporary config set so peaople can keep their cfgs
if myclass == "SHAMAN" and cfg.enable_totembar and not cfg.config_totembar[4] then
	local TotemBar = CreateHolder("holder_TotemBar", cfg.frame_positions[9])
	local tN = { 2, 1, 3, 4 }
	local TotemButtons = {
		MultiCastSummonSpellButton,
		MultiCastActionPage1,
		MultiCastActionPage2,
		MultiCastActionPage3,
		MultiCastSlotButton1,
		MultiCastSlotButton2,
		MultiCastSlotButton3,
		MultiCastSlotButton4,
		MultiCastFlyoutFrame,
		MultiCastFlyoutButton,
		MultiCastRecallSpellButton,
	}
 	if MultiCastActionBarFrame then
		TotemBar:SetSize(_G['MultiCastActionBarFrame']:GetWidth(), _G['MultiCastActionBarFrame']:GetHeight()) 
		TotemBar:SetAlpha(cfg.config_totembar[5] or 1)
		TotemBar:Show()
		for _, f in pairs(TotemButtons) do
			f:SetParent(TotemBar);
		end
		MultiCastSummonSpellButton:ClearAllPoints();
		MultiCastSummonSpellButton:SetPoint("BOTTOMLEFT");
		local page;
		for i = 1, NUM_MULTI_CAST_PAGES do
			page = _G["MultiCastActionPage"..i];
			page:SetPoint("BOTTOMLEFT");
		end
		MultiCastSummonSpellButton:SetSize(cfg.config_totembar[2],cfg.config_totembar[2])
		MultiCastRecallSpellButton:SetSize(cfg.config_totembar[2],cfg.config_totembar[2])
		for i = 1, 12 do
			local b = _G["MultiCastSlotButton"..i]
			local b2 = _G["MultiCastActionButton"..i]
			b2:SetSize(cfg.config_totembar[2],cfg.config_totembar[2])
			if b then
			b:ClearAllPoints()
			b:SetAllPoints(b2)
			end
 			if i == 1 or i == 5 or i == 9 then 
				b2:SetPoint("LEFT",MultiCastSummonSpellButton,"RIGHT",cfg.config_totembar[3]-1,0)
			else
				b2:SetPoint("LEFT",_G["MultiCastActionButton"..(i-1)],"RIGHT",cfg.config_totembar[3],0)
			end
		end
		MultiCastRecallSpellButton:SetPoint("TOPLEFT",MultiCastSlotButton4,"TOPRIGHT", cfg.config_totembar[3]-1, 0)
		MultiCastRecallSpellButton:SetPoint("BOTTOMLEFT",MultiCastSlotButton4,"BOTTOMRIGHT")
	end
	
	-- right click to destroy totem
	local function TotemBar_Destroy(self, button)
		if (button ~= "RightButton") then return end
		if (self:GetName() == "MultiCastActionButton1") or (self:GetName() == "MultiCastActionButton5") or (self:GetName() == "MultiCastActionButton9") then
			DestroyTotem(2);
		elseif (self:GetName() == "MultiCastActionButton2") or (self:GetName() == "MultiCastActionButton6") or (self:GetName() == "MultiCastActionButton10") then
			DestroyTotem(1);
		elseif (self:GetName() == "MultiCastActionButton3") or (self:GetName() == "MultiCastActionButton7") or (self:GetName() == "MultiCastActionButton11") then
			DestroyTotem(3);
		elseif (self:GetName() == "MultiCastActionButton4") or (self:GetName() == "MultiCastActionButton8") or (self:GetName() == "MultiCastActionButton12") then
			DestroyTotem(4);
		end
	end
	for i = 1, 12 do
		hooker = _G["MultiCastActionButton"..i];
		hooker:RegisterForClicks("LeftButtonUp")
		hooker:HookScript("OnMouseUp", TotemBar_Destroy)
		-- TotemBar:SetFrameRef("MultiCastActionButton"..i, hooker)
		-- TotemBar:WrapScript(hooker, "OnEnter", [[  
			-- if IsAltKeyDown() then
				-- print('ghetto debugging')
			-- end
		-- ]])
	end
	-- totem timers
	if cfg.config_totembar[1] then
		TotemBar.OnUpdate = function(self, elapsed)
			self.elapsed = self.elapsed + elapsed
			if self.elapsed > 0.2 then
				local tl = GetTotemTimeLeft(self.tN)
				if tl > 0 then
					self.t:SetFormattedText(SecondsToTimeAbbrev(tl))
					self.elapsed = 0
				else
					self.t:SetText("")
					self:Hide()
				end
			end
		end
		TotemBar.OnEvent = function(self, event, tN)
			if event == "PLAYER_ENTERING_WORLD" then tN = self.tN elseif tN ~= self.tN then	return end
			local _, _, start, duration = GetTotemInfo(tN)
			if duration > 0 then
				self.start = start
				self.duration = duration
				self:Show()
			else
				self:Hide()
			end
		end
		for i = 1, #tN do
			local btn = _G["MultiCastActionButton"..i]
			local h = CreateFrame("Frame", nil, btn)
			h.tN = tN[i]
			h:SetAllPoints(btn)
			h.bg = h:CreateTexture(nil, "BACKGROUND")
			h.bg:SetPoint("BOTTOM",h,"BOTTOM")
			h.bg:SetSize(h:GetHeight(),h:GetHeight()/3)
			h.bg:SetTexture(0, 0, 0)
			h.bg:SetAlpha(0.5)
			h.t = h:CreateFontString(nil, "OVERLAY")
			h.t:SetPoint("BOTTOM", h, "BOTTOM", 0, -1)
			h.t:SetWidth(h:GetWidth())
			h.t:SetFont("Fonts\\FRIZQT__.ttf", 11, "THINOUTLINE")
			h.t:SetTextColor(.6,.8,.4)
			h:SetScript("OnEvent", TotemBar.OnEvent)
			h:SetScript("OnUpdate", TotemBar.OnUpdate)
			h:SetScript("OnHide", function(self) self.start = nil self.duration = nil end)
			h:SetScript("OnShow", function(self) if not self.start or not self.duration then return self:Hide() end	self.elapsed = 1000 end)
			h:RegisterEvent("PLAYER_ENTERING_WORLD")
			h:RegisterEvent("PLAYER_TOTEM_UPDATE")
			TotemBar.OnEvent(h, "PLAYER_TOTEM_UPDATE", h.tN)
		end
	end

--[[ 	cfg.totembar_modifier = "ALT"		--
	cfg.totembar_flyout_button = false	--
--hooksecurefunc("MultiCastFlyoutFrameOpenButton_Show", function(self)
hooksecurefunc("MultiCastFlyoutFrameOpenButton_Show", function(self)
	if cfg.totembar_modifier=="ALT" and IsAltKeyDown() then
		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, self.type, self.parent);
	elseif cfg.totembar_modifier=="CTRL" and IsControlKeyDown() then
		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, self.type, self.parent);
	elseif cfg.totembar_modifier=="SHIFT" and IsShiftKeyDown() then
		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, self.type, self.parent);
	elseif cfg.totembar_modifier=="ANY" and IsModifierKeyDown() then
		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, self.type, self.parent);
	end
	if not cfg.totembar_flyout_button then
		MultiCastFlyoutFrameOpenButton_Hide(self,true)
	end
end) ]]

end

if not cfg.enable_action_bars then return end
if IsAddOnLoaded("Dominos") then return end

-- enabling default action bars
local f = CreateFrame"Frame"
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:SetScript("OnEvent", function()
	SHOW_MULTI_ACTIONBAR_1 = 1
	SHOW_MULTI_ACTIONBAR_2 = 1
	SHOW_MULTI_ACTIONBAR_3 = 1
	SHOW_MULTI_ACTIONBAR_4 = 1
	MultiActionBar_Update()
	SetActionBarToggles(1, 1, 1, 1)
end)

-- style function for bars
local SetBar = function(bar, button, num, orient, rows, visnum, bsize, spacing)
	local pad = spacing or cfg.spacing
	local first_row_num = math.floor(visnum/rows)
	for i = 1, num do
		_G[button..i]:ClearAllPoints()
		_G[button..i]:SetSize(bsize,bsize)
		if i == 1 then
			_G[button..i]:SetPoint("TOPLEFT", bar, "TOPLEFT", 0, 0)
		else
			if orient == "H" then
				if rows == 1 then
					_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-1)], "TOPRIGHT", pad, 0)
				else
					_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-1)], "TOPRIGHT", pad, 0)
					if i == first_row_num+1 then
						_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-first_row_num)], "BOTTOMLEFT", 0, -pad)
					end
					if i==first_row_num*2+1 then
						_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-first_row_num)], "BOTTOMLEFT", 0, -pad)
					end
				end
			else
				if rows == 1 then
					_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-1)], "BOTTOMLEFT", 0, -pad)
				else
					_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-1)], "BOTTOMLEFT", 0, -pad)
					if i == first_row_num+1 then
						_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-first_row_num)], "TOPRIGHT", pad, 0)
					end
					if i==first_row_num*2+1 then
						_G[button..i]:SetPoint("TOPLEFT", _G[button..(i-first_row_num)], "TOPRIGHT", pad, 0)
					end
				end
			end
			if i > visnum then 
				_G[button..i]:UnregisterAllEvents()
				_G[button..i]:SetScale(0.00001)
				_G[button..i]:SetAlpha(0)
				_G[button..i]:Hide()
			end
		end
		_G[button..i].SetPoint = null
	end
	if orient == "H" then
		if rows == 1 then
			bar:SetWidth(bsize*visnum + pad*(visnum-1))
			bar:SetHeight(bsize)
		else
			bar:SetWidth(bsize*first_row_num + pad*(first_row_num-1))
			bar:SetHeight(bsize*rows+pad)
		end
	else
		if rows == 1 then
			bar:SetWidth(bsize)
			bar:SetHeight(bsize*visnum + pad*(visnum-1))
		else
			bar:SetWidth(bsize*rows+pad)
			bar:SetHeight(bsize*first_row_num + pad*(first_row_num-1))
		end
	end
end

-- mouseover visibility condition
local SetBarAlpha = function(bar,button,num,switch,baralpha, fadealpha)
	if switch then
		local function lighton(alpha)
		  if bar and bar:IsShown() then
			for i=1, num do
			  local pb = _G[button..i]
			  pb:SetAlpha(alpha)
			end
		  end
		end    
		bar:EnableMouse(true)
		bar:SetScript("OnEnter", function(self) lighton(1) end)
		bar:SetScript("OnLeave", function(self) lighton(fadealpha or 0) end)  
		for i=1, num do
		  local pb = _G[button..i]
		  pb:SetAlpha(fadealpha or 0)
		  pb:HookScript("OnEnter", function(self) lighton(1) end)
		  pb:HookScript("OnLeave", function(self) lighton(fadealpha or 0) end)
		end
	end
	bar:SetAlpha(baralpha or 1)
end

-- combat visibility condition
local ShowInCombat = function(bar)
	bar:RegisterEvent("PLAYER_REGEN_DISABLED")
	bar:RegisterEvent("PLAYER_REGEN_ENABLED")
	bar:RegisterEvent("PLAYER_ENTERING_WORLD")
	bar:Hide()
	bar:SetScript("OnEvent", function(self, event, ...)
		if event == "PLAYER_REGEN_DISABLED" then 
			bar:Show()
		elseif event == "PLAYER_REGEN_ENABLED" then 
			bar:Hide()
		end
	end)
end

---- Modifying default action bars
-- Creating holder frames for each bar
local mainbar = CreateHolder("holder_MainBar", cfg.frame_positions[1])
local bottomleftbar = CreateHolder("holder_MultiBarBottomLeftBar", cfg.frame_positions[2])
local bottomrightbar = CreateHolder("holder_MultiBarBottomRightBar", cfg.frame_positions[3])
local leftbar = CreateHolder("holder_MultiBarLeftBar", cfg.frame_positions[4])
local rightbar = CreateHolder("holder_MultiBarRightBar", cfg.frame_positions[5])
local shapeshiftbar = CreateHolder("holder_ShapeShiftBar", cfg.frame_positions[6])
local petbar -- some mombo jumbo stuff for pet bar positioning for DKs and Shamans (specifically for MonoUI)
if myclass == "DEATHKNIGHT" or (myclass == "SHAMAN" and IsAddOnLoaded("oUF_TotemBar")) then
	petbar = CreateHolder("holder_PetBar", cfg.frame_positions[8]) 
else
	petbar = CreateHolder("holder_PetBar", cfg.frame_positions[7])
end
local MicroMenu = CreateHolder("holder_MicroMenu", cfg.frame_positions[11])


-- MainBar is a special bar and like everything special it requires SPECIAL handling
-- Major credits to Tukz for figuring out the way to operate with RegisterStateDriver()
local Page = {
    ["DRUID"] = "[bonusbar:1,nostealth] 7; [bonusbar:1,stealth] %s; [bonusbar:2] 8; [bonusbar:3] 9; [bonusbar:4] 10;",
    ["WARRIOR"] = "[bonusbar:1] 7; [bonusbar:2] 8; [bonusbar:3] 9;",
    ["PRIEST"] = "[bonusbar:1] 7;",
    ["ROGUE"] = "[bonusbar:1] 7; [form:3] 8;",
    ["WARLOCK"] = "[form:2] 7;",
    ["DEFAULT"] = "[bar:2] 2; [bar:3] 3; [bar:4] 4; [bar:5] 5; [bar:6] 6; [bonusbar:5] 11;",
}
local function GetBar()
    local condition = Page["DEFAULT"]
    local page = Page[myclass]
    if page then
      if myclass == "DRUID" then
        -- Handles prowling, prowling has no real stance, so this is a hack which utilizes the Tree of Life bar for non-resto druids.
        if IsSpellKnown(33891) then -- Tree of Life form
          page = page:format(7)
        else
          page = page:format(8)
        end
      end
      condition = condition.." "..page
    end
    condition = condition.." 1"
    return condition
end
local first_row_num = math.floor(cfg.config_mainbar[3]/cfg.config_mainbar[2])
if cfg.config_mainbar[1] == "H" then
	if cfg.config_mainbar[2] == 1 then
		mainbar:SetWidth(cfg.config_mainbar[4]*cfg.config_mainbar[3] + cfg.config_mainbar[5]*(cfg.config_mainbar[3]-1))
		mainbar:SetHeight(cfg.config_mainbar[4])
	else
		mainbar:SetWidth(cfg.config_mainbar[4]*first_row_num + cfg.config_mainbar[5]*(first_row_num-1))
		mainbar:SetHeight(cfg.config_mainbar[4]*cfg.config_mainbar[2]+cfg.config_mainbar[5])
	end
else
	if cfg.config_mainbar[2] == 1 then
		mainbar:SetWidth(cfg.config_mainbar[4])
		mainbar:SetHeight(cfg.config_mainbar[4]*cfg.config_mainbar[3] + cfg.config_mainbar[5]*(cfg.config_mainbar[3]-1))
	else
		mainbar:SetWidth(cfg.config_mainbar[4]*cfg.config_mainbar[2]+cfg.config_mainbar[5])
		mainbar:SetHeight(cfg.config_mainbar[4]*first_row_num + cfg.config_mainbar[5]*(first_row_num-1))
	end
end
mainbar:RegisterEvent("PLAYER_LOGIN")
mainbar:RegisterEvent("PLAYER_ENTERING_WORLD")
mainbar:RegisterEvent("KNOWN_CURRENCY_TYPES_UPDATE")
mainbar:RegisterEvent("CURRENCY_DISPLAY_UPDATE")
mainbar:RegisterEvent("BAG_UPDATE")
mainbar:RegisterEvent("PLAYER_REGEN_DISABLED")
mainbar:RegisterEvent("PLAYER_REGEN_ENABLED")
mainbar:SetScript("OnEvent", function(self, event, ...)
if event == "PLAYER_LOGIN" then
    local button, buttons
	for i = 1, NUM_ACTIONBAR_BUTTONS do
		button = _G["ActionButton"..i]
		self:SetFrameRef("ActionButton"..i, button)
	end  
	self:Execute([[
		buttons = table.new()
		for i = 1, 12 do
			table.insert(buttons, self:GetFrameRef("ActionButton"..i))
		end
		]])
	self:SetAttribute("_onstate-page", [[ 
		  for i, button in ipairs(buttons) do
			button:SetAttribute("actionpage", tonumber(newstate))
		  end
		]])
	RegisterStateDriver(self, "page", GetBar())
elseif event == "PLAYER_ENTERING_WORLD" then
	MainMenuBar_UpdateKeyRing()
	local button
		for i = 1, cfg.config_mainbar[3] do
			button = _G["ActionButton"..i]
			button:ClearAllPoints()
			button:SetSize(cfg.config_mainbar[4],cfg.config_mainbar[4])
			button:SetParent(self)
			previous = _G["ActionButton"..i-1]
			if i == 1 then
				button:SetPoint("TOPLEFT", mainbar, "TOPLEFT", 0,0)
			else
				if cfg.config_mainbar[1] == "H" then
					if cfg.config_mainbar[2] == 1 then
						button:SetPoint("TOPLEFT", previous, "TOPRIGHT", cfg.config_mainbar[5], 0)
					else
						button:SetPoint("TOPLEFT", previous, "TOPRIGHT", cfg.config_mainbar[5], 0)
						if i == first_row_num+1 then
							button:SetPoint("TOPLEFT", _G["ActionButton"..(i-first_row_num)], "BOTTOMLEFT", 0, -cfg.config_mainbar[5])
						end
						if i==first_row_num*2+1 then
							button:SetPoint("TOPLEFT", _G["ActionButton"..(i-first_row_num)], "BOTTOMLEFT", 0, -cfg.config_mainbar[5])
						end
					end
				else
					if cfg.config_mainbar[2] == 1 then
						button:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -cfg.config_mainbar[5])
					else
						button:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -cfg.config_mainbar[5])
						if i == first_row_num+1 then
							button:SetPoint("TOPLEFT", _G["ActionButton"..(i-first_row_num)], "TOPRIGHT", cfg.config_mainbar[5], 0)
						end
						if i==first_row_num*2+1 then
							button:SetPoint("TOPLEFT", _G["ActionButton"..(i-first_row_num)], "TOPRIGHT", cfg.config_mainbar[5], 0)
						end
					end
				end
			end
		end
	else
		MainMenuBar_OnEvent(self, event, ...)
	end
	-- visibility options for mainbar
	if cfg.config_mainbar[6] then mainbar:Hide() return end
	if cfg.config_mainbar[8] then 
		mainbar:Hide()
		if event == "PLAYER_REGEN_DISABLED" then 
			mainbar:Show()
		elseif event == "PLAYER_REGEN_ENABLED" then 
			mainbar:Hide()
		end
	end
end)

-- parenting action buttons to our holders
MultiBarBottomLeft:SetParent(bottomleftbar)
MultiBarBottomRight:SetParent(bottomrightbar)
MultiBarLeft:SetParent(leftbar)
MultiBarRight:SetParent(rightbar)
ShapeshiftBarFrame:SetParent(shapeshiftbar)
PetActionBarFrame:SetParent(petbar)
petbar:SetScale(0.805)

-- hiding posses bar since it's useless
PossessBarFrame:SetParent(shapeshiftbar)
PossessBarFrame:SetScale(0.0001)
PossessBarFrame:SetAlpha(0)

-- apply style settings
SetBar(bottomleftbar, "MultiBarBottomLeftButton", NUM_ACTIONBAR_BUTTONS, unpack(cfg.config_bottomleftbar))
SetBar(bottomrightbar, "MultiBarBottomRightButton", NUM_ACTIONBAR_BUTTONS, unpack(cfg.config_bottomrightbar))
SetBar(shapeshiftbar, "ShapeshiftButton", NUM_SHAPESHIFT_SLOTS, unpack(cfg.config_shapeshiftbar))
SetBar(leftbar, "MultiBarLeftButton", NUM_ACTIONBAR_BUTTONS, unpack(cfg.config_leftbar))
SetBar(rightbar, "MultiBarRightButton", NUM_ACTIONBAR_BUTTONS, unpack(cfg.config_rightbar))
SetBar(petbar, "PetActionButton", NUM_PET_ACTION_SLOTS, unpack(cfg.config_petbar))

-- mouseover functionality
SetBarAlpha(mainbar, "ActionButton", NUM_ACTIONBAR_BUTTONS, cfg.config_mainbar[7], cfg.config_mainbar[9], cfg.config_mainbar[10])
SetBarAlpha(bottomleftbar, "MultiBarBottomLeftButton", NUM_ACTIONBAR_BUTTONS, cfg.config_bottomleftbar[7], cfg.config_bottomleftbar[9], cfg.config_bottomleftbar[10])
SetBarAlpha(bottomrightbar, "MultiBarBottomRightButton", NUM_ACTIONBAR_BUTTONS, cfg.config_bottomrightbar[7], cfg.config_bottomrightbar[9], cfg.config_bottomrightbar[10])
SetBarAlpha(shapeshiftbar, "ShapeshiftButton", NUM_SHAPESHIFT_SLOTS, cfg.config_shapeshiftbar[7], cfg.config_shapeshiftbar[9], cfg.config_shapeshiftbar[10])
SetBarAlpha(leftbar, "MultiBarLeftButton", NUM_ACTIONBAR_BUTTONS, cfg.config_leftbar[7], cfg.config_leftbar[9], cfg.config_leftbar[10])
SetBarAlpha(rightbar, "MultiBarRightButton", NUM_ACTIONBAR_BUTTONS, cfg.config_rightbar[7], cfg.config_rightbar[9], cfg.config_rightbar[10])
SetBarAlpha(petbar, "PetActionButton", NUM_PET_ACTION_SLOTS, cfg.config_petbar[7], cfg.config_petbar[9], cfg.config_petbar[10])

-- apply visibility conditions
if cfg.config_bottomleftbar[6] then bottomleftbar:Hide() elseif cfg.config_bottomleftbar[8] then ShowInCombat(bottomleftbar) end
if cfg.config_bottomrightbar[6] then bottomrightbar:Hide() elseif cfg.config_bottomrightbar[8] then ShowInCombat(bottomrightbar) end
if cfg.config_leftbar[6] then leftbar:Hide() elseif cfg.config_leftbar[8] then ShowInCombat(leftbar) end
if cfg.config_rightbar[6] then rightbar:Hide() elseif cfg.config_rightbar[8] then ShowInCombat(rightbar) end
if cfg.config_shapeshiftbar[6] then shapeshiftbar:Hide() elseif cfg.config_shapeshiftbar[8] then ShowInCombat(shapeshiftbar) end
if cfg.config_petbar[6] then petbar:Hide() elseif cfg.config_petbar[8] then ShowInCombat(petbar) end

-- hiding default frames and textures
MainMenuBar:EnableMouse(false)
MainMenuBar:SetScale(0.0001)
VehicleMenuBar:EnableMouse(false)
VehicleMenuBar:SetScale(0.0001)
PetActionBarFrame:EnableMouse(false)
MainMenuBarMaxLevelBar:EnableMouse(false)
local FramesToHide = {
	MainMenuBar, 
	MainMenuBarArtFrame, 
	BonusActionBarFrame, 
	VehicleMenuBar,
	PossessBarFrame}
for _, f in pairs(FramesToHide) do
    if f:GetObjectType() == "Frame" then
      f:UnregisterAllEvents()
    end
    if f ~= MainMenuBar then --patch 4.0.6 fix, credits to tukz
      f:HookScript("OnShow", function(s) s:Hide(); end)
      f:Hide()
	end
    f:SetAlpha(0)
end

-- exit vehicle button for the lazy ones
local ve = CreateFrame("BUTTON", "holder_VEB", UIParent, "SecureActionButtonTemplate")
ve:SetSize(cfg.config_mainbar[4]+10,cfg.config_mainbar[4]+10)
if cfg.VEB_user_placed then 
	ve:SetPoint(cfg.frame_positions[14].a, cfg.frame_positions[14].x, cfg.frame_positions[14].y)
else
	ve:SetPoint("CENTER", ActionButton8, "CENTER", cfg.config_mainbar[5]/2, 0)
end
ve:RegisterForClicks("AnyUp")
ve:SetScript("OnClick", function() VehicleExit() end)
ve:SetNormalTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up")
ve:SetPushedTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Down")
ve:SetHighlightTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Down")
ve:SetAlpha(0)
-- adding border so it fits our bars general style
local veh = CreateFrame("Frame",nil,ve)
veh:SetAllPoints(ve)
veh:SetParent(ve)
veh:SetFrameLevel(31)
veh:EnableMouse(false)
local veb = veh:CreateTexture(cfg.textures_normal)
veb:SetTexture(cfg.textures_normal)
veb:SetPoint("TOPLEFT",4,-5)
veb:SetPoint("BOTTOMRIGHT",-6,5)
veb:SetVertexColor(0,0,0)
ve:Hide()
if not cfg.hide_exit_vehicle_button then
	ve:Show()
	ve:RegisterEvent("UNIT_ENTERING_VEHICLE")
	ve:RegisterEvent("UNIT_ENTERED_VEHICLE")
	ve:RegisterEvent("UNIT_EXITING_VEHICLE")
	ve:RegisterEvent("UNIT_EXITED_VEHICLE")
	ve:RegisterEvent("ZONE_CHANGED_NEW_AREA")
	ve:SetScript("OnEvent", function(self, event, ...)
		local arg1 = ...;
		if(((event=="UNIT_ENTERING_VEHICLE") or (event=="UNIT_ENTERED_VEHICLE")) and arg1 == "player") then
			ve:SetAlpha(1)
			ve:SetScript("OnEnter", function(self) 
				veb:SetVertexColor(cfg.colors.highlight.r, cfg.colors.highlight.g, cfg.colors.highlight.b)
			end)
			ve:SetScript("OnLeave", function(self) veb:SetVertexColor(cfg.colors.normal.r, cfg.colors.normal.g, cfg.colors.normal.b) end)
		elseif (((event=="UNIT_EXITING_VEHICLE") or (event=="UNIT_EXITED_VEHICLE")) and arg1 == "player") or (event=="ZONE_CHANGED_NEW_AREA" and not UnitHasVehicleUI("player")) then
			ve:SetAlpha(0)
		end
	end)  
end

-- MicroMenu
MicroMenu:SetSize(255,40)
MicroMenu:SetScale(cfg.micromenu_scale)
local MicroButtons = {
	CharacterMicroButton,
	SpellbookMicroButton,
	TalentMicroButton,
	AchievementMicroButton,
	QuestLogMicroButton,
	GuildMicroButton,
	PVPMicroButton,
	LFDMicroButton,
	MainMenuMicroButton,
	HelpMicroButton} 
local SetMicroButtons = function() 
    for _, b in pairs(MicroButtons) do
		b:SetParent(MicroMenu)
    end
    CharacterMicroButton:ClearAllPoints();
    CharacterMicroButton:SetPoint("BOTTOMLEFT", 0, 0)
end
SetMicroButtons()
-- gotta run this function each time we respec so we don't loose our micromenu bar
MicroMenu:RegisterEvent("PLAYER_TALENT_UPDATE")
MicroMenu:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
MicroMenu:SetScript("OnEvent", function(self,event) 
      if  not InCombatLockdown() and (event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED") then
          SetMicroButtons()
      end
end)
-- micro menu on mouseover
if cfg.micromenu_onmouseover then    
	local switcher = -1
	local function mmalpha(alpha)
		for _, f in pairs(MicroButtons) do
			f:SetAlpha(alpha)
			switcher = alpha
		end
	end
	MicroMenu:EnableMouse(true)
	MicroMenu:SetScript("OnEnter", function(self) mmalpha(1) end)
	MicroMenu:SetScript("OnLeave", function(self) mmalpha(0) end)
	for _, f in pairs(MicroButtons) do
		f:SetAlpha(0)
		f:HookScript("OnEnter", function(self) mmalpha(1) end)
		f:HookScript("OnLeave", function(self) mmalpha(0) end)
	end
	MicroMenu:SetScript("OnEvent", function(self) 
		mmalpha(0) 
	end)
	MicroMenu:RegisterEvent("PLAYER_ENTERING_WORLD")
	--fix for the talent button display while micromenu onmouseover
	local function TalentSwitchAlphaFix(self,alpha)
		if switcher ~= alpha then
			switcher = 0
			self:SetAlpha(0)
		end
		SetMicroButtons()
	end
	hooksecurefunc(TalentMicroButton, "SetAlpha", TalentSwitchAlphaFix)
end

-- fix main bar keybind not working after a talent switch, credits to tukz/evl22
hooksecurefunc('TalentFrame_LoadUI', function()
	PlayerTalentFrame:UnregisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
end)

-- rescale cooldown spiral to fix texture.
local buttonNames = { "ActionButton",  "MultiBarBottomLeftButton", "MultiBarBottomRightButton", "MultiBarLeftButton", "MultiBarRightButton", "ShapeshiftButton", "PetActionButton"}
for _, name in ipairs( buttonNames ) do
	for index = 1, 12 do
		local buttonName = name .. tostring(index)
		local button = _G[buttonName]
		local cooldown = _G[buttonName .. "Cooldown"]
 		if ( button == nil or cooldown == nil ) then
			break
		end
		cooldown:ClearAllPoints()
		cooldown:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2)
		cooldown:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
	end
end

-- RaidMark bar
local raidmarkbar = CreateHolder("holder_RaidMarkBar", cfg.frame_positions[12])
local SetRaidIconButton = function(icon,name,marknum,point,anchor,rpoint,offX,offY,tex,x1,x2,y1,y2)
local icon = CreateFrame("Button", name.."Icon", raidmarkbar)
	icon:SetSize(cfg.config_raidiconbar[2],cfg.config_raidiconbar[2])
	icon:SetPoint(point, anchor, rpoint, offX, offY)
	icon:SetNormalTexture(tex)
	icon:GetNormalTexture():SetTexCoord(x1,x2,y1,y2)
	icon:EnableMouse(true)
	icon:SetScript("OnClick", function(self) SetRaidTarget("target", 0); SetRaidTarget("target", marknum) end)
	icon.bd = icon:CreateTexture(cfg.textures_normal)
	icon.bd:SetTexture(cfg.textures_normal)
	icon.bd:SetPoint("TOPLEFT",-1,1)
	icon.bd:SetPoint("BOTTOMRIGHT",1,-1)
	icon.bd:SetVertexColor(cfg.colors.normal.r, cfg.colors.normal.g, cfg.colors.normal.b)
	icon.bg = CreateFrame("Frame",nil,icon)
	icon.bg:SetBackdrop({bgFile="interface\\Tooltips\\UI-Tooltip-Background"})
	icon.bg:SetBackdropColor(0,0,0,.8)
	icon.bg:SetAllPoints(icon)
	icon.bg:SetFrameStrata("BACKGROUND")
	icon:SetScript("OnEnter", function(self) 
		GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT"); GameTooltip:ClearLines(); GameTooltip:AddLine(name, 0.88,0.65,0); GameTooltip:Show() 
		icon.bd:SetVertexColor(cfg.colors.highlight.r, cfg.colors.highlight.g, cfg.colors.highlight.b)
	end)
	icon:SetScript("OnLeave", function(self) GameTooltip:Hide() icon.bd:SetVertexColor(cfg.colors.normal.r, cfg.colors.normal.g, cfg.colors.normal.b) end)
end
local i_rpoint, i_point, i_offX, i_offY
local icontextable = "interface\\targetingframe\\ui-raidtargetingicons"
if cfg.config_raidiconbar[1] == "H" then
	i_point = "LEFT"
	i_rpoint = "RIGHT"
	i_offX = cfg.config_raidiconbar[3]+2
	i_offY = 0
	SetRaidIconButton(IconSkull,"Skull",8,"LEFT",raidmarkbar,"LEFT",i_offX,i_offY,icontextable,0.75,1,0.25,0.5)
	raidmarkbar:SetSize((cfg.config_raidiconbar[2]+cfg.config_raidiconbar[3]+2)*9,cfg.config_raidiconbar[2])
else
	i_point = "TOP"
	i_rpoint = "BOTTOM"
	i_offX = 0
	i_offY = -(cfg.config_raidiconbar[3]+2)
	SetRaidIconButton(IconSkull,"Skull",8,"TOP",raidmarkbar,"TOP",i_offX,i_offY,icontextable,0.75,1.01,0.24,0.51)
	raidmarkbar:SetSize(cfg.config_raidiconbar[2],(cfg.config_raidiconbar[2]+cfg.config_raidiconbar[3]+2)*9)
end
SetRaidIconButton(IconCross,"Cross",7,i_point,SkullIcon,i_rpoint,i_offX,i_offY,icontextable,0.5,0.75,0.25,0.5)
SetRaidIconButton(IconSquare,"Square",6,i_point,CrossIcon,i_rpoint,i_offX,i_offY,icontextable,0.25,0.5,0.25,0.5)
SetRaidIconButton(IconMoon,"Moon",5,i_point,SquareIcon,i_rpoint,i_offX,i_offY,icontextable,0,0.25,0.25,0.5)
SetRaidIconButton(IconTriangle,"Triangle",4,i_point,MoonIcon,i_rpoint,i_offX,i_offY,icontextable,0.75,1,0,0.25)
SetRaidIconButton(IconDiamond,"Diamond",3,i_point,TriangleIcon,i_rpoint,i_offX,i_offY,icontextable,0.5,0.75,0,0.25)
SetRaidIconButton(IconCircle,"Circle",2,i_point,DiamondIcon,i_rpoint,i_offX,i_offY,icontextable,0.25,0.5,0,0.25)
SetRaidIconButton(IconStar,"Star",1,i_point,CircleIcon,i_rpoint,i_offX,i_offY,icontextable,0,0.25,0,0.25)
SetRaidIconButton(IconClear,"Clear",0,i_point,StarIcon,i_rpoint,i_offX,i_offY,"interface\\glues\\loadingscreens\\dynamicelements",0,0.5,0,0.5)

-- World marker flare bar
local worldmarkbar = CreateHolder("holder_WorldMarkBar", cfg.frame_positions[13])
local SetFlareButton = function(flare,name,flarenum,point,anchor,rpoint,offX,offY,tex,x1,x2,y1,y2)
	local flare = CreateFrame("Button", name.."Flare", worldmarkbar, "SecureActionButtonTemplate")
	flare:SetSize(cfg.config_markerflarebar[2],cfg.config_markerflarebar[2])
	flare:SetNormalTexture(tex)
	flare:GetNormalTexture():SetTexCoord(x1,x2,y1,y2)
	flare:SetPoint(point, anchor, rpoint, offX, offY)
	flare:SetAttribute("type", "macro")
	flare:SetAttribute("macrotext1", "/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton\n/click DropDownList1Button"..flarenum)
	flare.bd = flare:CreateTexture(cfg.textures_normal)
	flare.bd:SetTexture(cfg.textures_normal)
	flare.bd:SetPoint("TOPLEFT",-1,1)
	flare.bd:SetPoint("BOTTOMRIGHT",1,-1)
	flare.bd:SetVertexColor(cfg.colors.normal.r, cfg.colors.normal.g, cfg.colors.normal.b)
	flare.bg = CreateFrame("Frame",nil,flare)
	flare.bg:SetBackdrop({bgFile="interface\\Tooltips\\UI-Tooltip-Background"})
	flare.bg:SetBackdropColor(0,0,0,.8)
	flare.bg:SetAllPoints(flare)
	flare.bg:SetFrameStrata("BACKGROUND")
	flare:SetScript("OnEnter", function(self) 
		GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT"); GameTooltip:ClearLines(); GameTooltip:AddLine(name.." world marker",0.88,0.65,0); GameTooltip:Show() 
		flare.bd:SetVertexColor(cfg.colors.highlight.r, cfg.colors.highlight.g, cfg.colors.highlight.b)
	end)
	flare:SetScript("OnLeave", function(self) GameTooltip:Hide() flare.bd:SetVertexColor(cfg.colors.normal.r, cfg.colors.normal.g, cfg.colors.normal.b) end)
end

local f_rpoint, f_point, f_offX, f_offY
if cfg.config_markerflarebar[1] == "H" then
	f_point = "LEFT"
	f_rpoint = "RIGHT"
	f_offX = cfg.config_markerflarebar[3]+2
	f_offY = 0
	SetFlareButton(BlueFlare,"Blue",1,"LEFT",worldmarkbar,"LEFT",f_offX,f_offY,icontextable,0.25,0.5,0.25,0.5)
	worldmarkbar:SetSize((cfg.config_markerflarebar[2]+cfg.config_markerflarebar[3]+2)*6,cfg.config_markerflarebar[2])
else
	f_point = "TOP"
	f_rpoint = "BOTTOM"
	f_offX = 0
	f_offY = -(cfg.config_markerflarebar[3]+2)
	SetFlareButton(BlueFlare,"Blue",1,"TOP",worldmarkbar,"TOP",f_offX,f_offY,icontextable,0.25,0.5,0.25,0.5)
	worldmarkbar:SetSize(cfg.config_markerflarebar[2],(cfg.config_markerflarebar[2]+cfg.config_markerflarebar[3]+2)*6)
end
SetFlareButton(GreenFlare,"Green",2,f_point,BlueFlare,f_rpoint,f_offX,f_offY,icontextable,0.75,1,0,0.25)
SetFlareButton(PurpleFlare,"Purple",3,f_point,GreenFlare,f_rpoint,f_offX,f_offY,icontextable,0.5,0.75,0,0.25)
SetFlareButton(RedFlare,"Red",4,f_point,PurpleFlare,f_rpoint,f_offX,f_offY,icontextable,0.5,0.75,0.25,0.5)
SetFlareButton(WhiteFlare,"White",5,f_point,RedFlare,f_rpoint,f_offX,f_offY,icontextable,0,0.25,0,0.25)
SetFlareButton(ClearFlare,"Clear",6,f_point,WhiteFlare,f_rpoint,f_offX,f_offY,"interface\\glues\\loadingscreens\\dynamicelements",0,0.5,0,0.5)

-- Mouseover alpha for raid mark/flare bars
local SetRaidMarksAlpha = function(bar,buttons,switch,baralpha,fadealpha,disable)
	if disable and InCombatLockdown() then -- temporarily disable mouseover functionality when needed
		return
	end
	if switch then
		local switcher = -1
		local function mmalpha(alpha)
			for _, f in pairs(buttons) do
				f:SetAlpha(alpha)
				switcher = alpha
			end
		end
		bar:EnableMouse(true)
		bar:SetScript("OnEnter", function(self) mmalpha(1) end)
		bar:SetScript("OnLeave", function(self) mmalpha(fadealpha) end)
		for _, f in pairs(buttons) do
			f:SetAlpha(fadealpha)
			f:HookScript("OnEnter", function(self) mmalpha(1) end)
			f:HookScript("OnLeave", function(self) mmalpha(fadealpha) end)
		end
		bar:SetScript("OnEvent", function(self) 
			mmalpha(fadealpha) 
		end)
		bar:RegisterEvent("PLAYER_ENTERING_WORLD")
	end
	bar:SetAlpha(baralpha)
end
local RaidIconButtons = {SkullIcon,CrossIcon,SquareIcon,MoonIcon,TriangleIcon,DiamondIcon,CircleIcon,StarIcon,ClearIcon} 
local WorldMarkButtons = {BlueFlare,GreenFlare,PurpleFlare,RedFlare,WhiteFlare,ClearFlare} 
SetRaidMarksAlpha(raidmarkbar,RaidIconButtons,cfg.config_raidiconbar[5],cfg.config_raidiconbar[7],cfg.config_raidiconbar[8])
SetRaidMarksAlpha(worldmarkbar,WorldMarkButtons,cfg.config_markerflarebar[5],cfg.config_markerflarebar[7],cfg.config_markerflarebar[8],true)

-- set up visibility conditions for WorldMark and RaidMark bars
if cfg.config_raidiconbar[4] then 
	holder_RaidMarkBar:Hide() 
elseif cfg.config_raidiconbar[6] then 
	ShowInCombat(holder_RaidMarkBar) 
end
holder_WorldMarkBar:RegisterEvent("PLAYER_REGEN_DISABLED")
holder_WorldMarkBar:RegisterEvent("PLAYER_REGEN_ENABLED")
holder_WorldMarkBar:RegisterEvent("PLAYER_ENTERING_WORLD")
holder_WorldMarkBar:RegisterEvent("PARTY_MEMBERS_CHANGED")
holder_WorldMarkBar:RegisterEvent("PARTY_LEADER_CHANGED")
holder_WorldMarkBar:Show()
holder_WorldMarkBar:SetScript("OnEvent", function(self, event, ...)
	if cfg.config_markerflarebar[4] then self:Hide() return	end
	if InCombatLockdown() then return end
	if event == "PLAYER_REGEN_DISABLED" then self:Hide() return	end
	if cfg.config_markerflarebar[6] and (GetNumRaidMembers() + GetNumPartyMembers() == 0) then	self:Hide()	return end
	if not (IsRaidOfficer()==1 or IsRaidLeader()==1 or IsPartyLeader()) then self:Hide() return end
	self:Show()
end)

-- hiding extra bars
local bars_visible
if cfg.hide_side_bars then
	leftbar:Hide()
	rightbar:Hide()
	bars_visible = false
end
if cfg.hide_micromenu then MicroMenu:Hide() end

-- making this global function to hook in my broker toggler
m_ActionBars_Toggle_Extra_Bars = function()
	if InCombatLockdown() then return print("m_ActionBars: Вы не можете переключать панели во время боя!") end
	if bars_visible then 
		if cfg.hide_side_bars then
			leftbar:Hide()
			rightbar:Hide()
		end
		if cfg.config_shapeshiftbar[6] then shapeshiftbar:Hide() end
		if cfg.hide_micromenu then MicroMenu:Hide() end
		if holder_WorldMarkBar and cfg.config_markerflarebar[4] then holder_WorldMarkBar:Hide() end
		if holder_RaidMarkBar and cfg.config_raidiconbar[4] then holder_RaidMarkBar:Hide() end
		bars_visible = false
	else
		if cfg.hide_side_bars then
			leftbar:Show()
			rightbar:Show()
		end
		if cfg.config_shapeshiftbar[6] then shapeshiftbar:Show() end
		if cfg.hide_micromenu then MicroMenu:Show() end
		if cfg.config_markerflarebar[4] and holder_WorldMarkBar then holder_WorldMarkBar:Show() end
		if cfg.config_raidiconbar[4] and holder_RaidMarkBar then holder_RaidMarkBar:Show() end
		bars_visible = true
	end
end

-- and making slash command to show them
SlashCmdList["EXTRA"] = function() m_ActionBars_Toggle_Extra_Bars() end
SLASH_EXTRA1 = "/extra"
SLASH_EXTRA2 = "/eb"

-- adding testmode to make bar positioning easier
local testmodeON
m_ActionBars_Toggle_Test_Mode = function()
	local def_back		= "interface\\Tooltips\\UI-Tooltip-Background"
	local backdrop_tab = { 
		bgFile = def_back, 
		edgeFile = nil,
		tile = false, tileSize = 0, edgeSize = 5, 
		insets = {left = 0, right = 0, top = 0, bottom = 0,},}
	local ShowHolder = function(holder, switch)
		if not _G[holder:GetName().."_overlay"] then
			local f = CreateFrame("Frame", holder:GetName().."_overlay")
			f:SetAllPoints(holder)
			f:SetBackdrop(backdrop_tab);
			f:SetBackdropColor(.1,.1,.2,.8)
			f:SetFrameStrata("HIGH")
			local name = f:CreateFontString(nil) 
			name:SetFont("Fonts\\FRIZQT__.TTF",8)
			name:SetText(holder:GetName())
			name:SetPoint("BOTTOMLEFT",f,"TOPLEFT")
		end

		if switch then
			_G[holder:GetName().."_overlay"]:Show()
		else
			_G[holder:GetName().."_overlay"]:Hide()
		end
	end
	if testmodeON then 
		testmodeON = false
	else
		testmodeON = true
	end
	local holders = {
		holder_MainBar,
		holder_MultiBarBottomLeftBar,
		holder_MultiBarBottomRightBar,
		holder_MultiBarLeftBar,
		holder_MultiBarRightBar,
		holder_ShapeShiftBar,
		holder_PetBar,
		holder_MicroMenu,
		holder_RaidMarkBar,
		holder_WorldMarkBar,
		holder_VEB}
	for _, f in pairs(holders) do
		ShowHolder(f,testmodeON)
	end
	if cfg.enable_totembar and myclass == "SHAMAN" then ShowHolder(holder_TotemBar,testmodeON) end
end
SlashCmdList["TESTMODE"] = function() m_ActionBars_Toggle_Test_Mode() end
SLASH_TESTMODE1 = "/mab"
SLASH_TESTMODE2 = "/tm"

ns.mAB = mAB