local _, ns = ...
local M, R, U, I = unpack(ns)
local S = M:GetModule("Skins")

local _G = _G
local strfind = strfind
local IsAddOnLoaded = C_AddOns.IsAddOnLoaded
local cr, cg, cb = I.r, I.g, I.b

function S:FriendGroups()
	--if not IsAddOnLoaded("FriendGroups") then return end

	if FriendGroups_UpdateFriendButton then
		local function replaceButtonStatus(self, texture)
			self:SetPoint("TOPLEFT", 4, 1)
			self.bg:Show()
			if strfind(texture, "PlusButton") then
				self:SetAtlas("Soulbinds_Collection_CategoryHeader_Collapse", true)
			elseif strfind(texture, "MinusButton") then
				self:SetAtlas("Soulbinds_Collection_CategoryHeader_Expand", true)
			else
				self:SetPoint("TOPLEFT", 4, -3)
				self.bg:Hide()
			end
		end

		hooksecurefunc("FriendGroups_UpdateFriendButton", function(button)
			if not button.styled then
				local bg = M.CreateBDFrame(button.status, .25)
				bg:SetInside(button.status, 3, 3)
				button.status.bg = bg
				hooksecurefunc(button.status, "SetTexture", replaceButtonStatus)

				button.styled = true
			end
		end)
	end
end

function S:PostalSkin()
	if not IsAddOnLoaded("Postal") then return end
	if not PostalOpenAllButton then return end -- outdate postal

	M.Reskin(PostalSelectOpenButton)
	M.Reskin(PostalSelectReturnButton)
	M.Reskin(PostalOpenAllButton)
	M.Reskin(PostalForwardButton)
	M.ReskinArrow(Postal_ModuleMenuButton, "down")
	M.ReskinArrow(Postal_OpenAllMenuButton, "down")
	for i = 1, 7 do
		local cb = _G["PostalInboxCB"..i]
		if cb then
			M.ReskinCheck(cb)
		end
	end

	Postal_ModuleMenuButton:ClearAllPoints()
	Postal_ModuleMenuButton:SetPoint("RIGHT", MailFrame.CloseButton, "LEFT", -2, 0)
	Postal_OpenAllMenuButton:SetPoint("LEFT", PostalOpenAllButton, "RIGHT", 2, 0)

	if Postal_BlackBookButton then
		M.ReskinArrow(Postal_BlackBookButton, "down")
		Postal_BlackBookButton:SetPoint("LEFT", SendMailNameEditBox, "RIGHT", 2, 0)
	end

	for i = 1, 16 do
		local button = _G["Postal_QuickAttachButton"..i]
		if button then
			button:GetNormalTexture():SetAlpha(0)
			button:GetPushedTexture():SetAlpha(0)
			button:GetHighlightTexture():SetColorTexture(1, 1, 1, .25)
			M.ReskinIcon(button.icon)
		end
	end
end

function S:SoulbindsTalents()
	if not IsAddOnLoaded("SoulbindsTalents") then return end

	hooksecurefunc("PanelTemplates_SetNumTabs", function(frame, num)
		if frame == _G.PlayerTalentFrame and num == 4 then
			if _G.PlayerTalentFrameTab4 then
				M.ReskinTab(_G.PlayerTalentFrameTab4)
			end
		elseif frame == _G.SoulbindAnchor then
			for i = 1, 4 do
				local tab = _G["SoulbindViewerTab"..i]
				if tab then
					M.ReskinTab(tab)
				end
			end
		end
	end)
end

local function restyleMRTWidget(self)
	local iconTexture = self.iconTexture
	local bar = self.statusbar
	local parent = self.parent
	local width = parent.barWidth or 100
	local mult = (parent.iconSize or 24) + 5
	local offset = 3

	if not self.styled then
		M.SetBD(iconTexture)
		self.__bg = M.SetBD(bar)
		self.background:SetAllPoints(bar)

		self.styled = true
	end
	iconTexture:SetTexCoord(unpack(I.TexCoord))
	self.__bg:SetShown(parent.optionAlphaTimeLine ~= 0)

	if parent.optionIconPosition == 3 or parent.optionIconTitles then
		self.statusbar:SetPoint("RIGHT", self, -offset, 0)
		mult = 0
	elseif parent.optionIconPosition == 2 then
		self.icon:SetPoint("RIGHT", self, -offset, 0)
		self.statusbar:SetPoint("LEFT", self, offset, 0)
		self.statusbar:SetPoint("RIGHT", self, -mult, 0)
	else
		self.icon:SetPoint("LEFT", self, offset, 0)
		self.statusbar:SetPoint("LEFT", self, mult, 0)
		self.statusbar:SetPoint("RIGHT", self, -offset, 0)
	end

	self.timeline.width = width - mult - offset
	self.timeline:SetWidth(self.timeline.width)
	self.border.top:Hide()
	self.border.bottom:Hide()
	self.border.left:Hide()
	self.border.right:Hide()
end

local MRTLoaded
local function LoadMRTSkin()
	if MRTLoaded then return end
	MRTLoaded = true

	local name = "MRTRaidCooldownCol"
	for i = 1, 10 do
		local column = _G[name..i]
		local lines = column and column.lines
		if lines then
			for j = 1, #lines do
				local line = lines[j]
				if line.UpdateStyle then
					hooksecurefunc(line, "UpdateStyle", restyleMRTWidget)
					line:UpdateStyle()
				end
			end
		end
	end
end

function S:MRT_Skin()
	if not IsAddOnLoaded("MRT") then return end

	local isEnabled = VMRT and VMRT.ExCD2 and VMRT.ExCD2.enabled
	if isEnabled then
		LoadMRTSkin()
	else
		hooksecurefunc(MRTOptionsFrameExCD2, "Load", function(self)
			if self.chkEnable then
				self.chkEnable:HookScript("OnClick", LoadMRTSkin)
			end
		end)
	end

	-- Consumables
	local buttons = MRTConsumables and MRTConsumables.buttons
	if buttons then
		for i = 1, 8 do
			local button = buttons[i]
			local icon = button and button.texture
			if icon then
				M.ReskinIcon(icon)
			end
		end
	end
end

local function updateSoulshapeButtons(self)
	local buttons = self.buttons
	for i = 1, #buttons do
		local bu = buttons[i]
		if not bu.bg then
			local bg = M.CreateBDFrame(bu, .25)
			bg:SetPoint("TOPLEFT", 3, -1)
			bg:SetPoint("BOTTOMRIGHT", 0, 1)
			bu.bg = bg

			M.ReskinIcon(bu.icon)
			bu.selectedTexture:SetAlpha(0)
			bu.background:SetTexture(nil)
			bu:SetHighlightTexture(0)

			local critterIcon = bu.critterIcon
			critterIcon:SetTexture("Interface\\ICONS\\Pet_Type_Critter")
			critterIcon:SetTexCoord(0, 1, 0, 1)
			critterIcon:SetSize(40, 40)
			critterIcon:SetAlpha(.5)
		end

		if bu.selected then
			bu.bg:SetBackdropColor(cr, cg, cb, .25)
		else
			bu.bg:SetBackdropColor(0, 0, 0, .25)
		end
	end
end

function S:ReskinSecureTabs()
	for i = 0, 10 do
		local tab = _G["CollectionsJournalSecureTab"..i]
		if not tab then break end
		if not tab.styled then
			M.ReskinTab(tab)
			tab.styled = true
		end
	end
end

function S:SoulshapeJournal()
	if not IsAddOnLoaded("SoulshapeJournal") then return end
	if not SoulshapeCollectionPanel then return end

	CollectionsJournalCoverTab:SetAlpha(0)
	S:ReskinSecureTabs()

	local styled
	SoulshapeCollectionPanel:HookScript("OnShow", function(frame)
		if styled then return end
		styled = true

		M.StripTextures(frame)
		M.SetBD(frame, 1) -- on top of mount journal
		M.ReskinClose(frame.CloseButton)
		M.ReskinScroll(frame.ScrollFrame.ScrollBar)
		M.ReskinArrow(frame.SoulshapeDisplay.ModelScene.RotateLeftButton, "left")
		M.ReskinArrow(frame.SoulshapeDisplay.ModelScene.RotateRightButton, "right")
		M.StripTextures(SoulshapeCollectionPanelCount)
		M.CreateBDFrame(SoulshapeCollectionPanelCount, .25)

		local searchBox, _, filterButton = select(11, frame:GetChildren())
		M.ReskinInput(searchBox)
		filterButton.Icon = select(12, filterButton:GetRegions())
		if filterButton.Icon then
			M.ReskinFilterButton(filterButton)
		end

		hooksecurefunc(frame.ScrollFrame, "update", updateSoulshapeButtons)
		hooksecurefunc(frame.ScrollFrame, "UpdateButtons", updateSoulshapeButtons)
	end)
end

function S:ATT()
	if not IsAddOnLoaded("AllTheThings") then return end

	local ATT = _G.AllTheThings
	if not ATT then return end

	local function reskinATTWindow(frame)
		if not frame or frame.styled then return end

		M.SetBD(frame, nil, 2, -2, -2, 2)
		M.ReskinClose(frame.CloseButton, nil, -4, -4)
		M.ReskinScroll(frame.ScrollBar)
		frame.Grip:SetTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Up]])
		local up = frame.ScrollBar:GetChildren()
		up:ClearAllPoints()
		up:SetPoint("TOPRIGHT", 0, 10)

		frame.styled = true
	end

	for _, frame in pairs(ATT.Windows) do
		reskinATTWindow(frame)
	end

	hooksecurefunc(ATT, "GetWindow", function(self, suffix)
		reskinATTWindow(self.Windows[suffix])
	end)
end

function S:TrinketMenu()
	if not IsAddOnLoaded("TrinketMenu") then return end

	local function reskinFrame(frame)
		if not frame then return end
		M.StripTextures(frame)
		M.SetBD(frame):SetInside(nil, 3, 3)
	end

	local function reskinButton(name)
		local button = _G[name]
		if not button then return end

		button:GetHighlightTexture():SetColorTexture(1, 1, 1, .25)
		button:SetPushedTexture(I.pushedTex)
		button:GetCheckedTexture():SetColorTexture(1, .8, 0, .5)
		_G[name.."NormalTexture"]:SetAlpha(0)
		M.ReskinIcon(_G[name.."Icon"])

		local queue = _G[name.."Queue"]
		if queue then queue:SetTexCoord(unpack(I.TexCoord)) end
	end

	reskinFrame(TrinketMenu_MainFrame)
	reskinButton("TrinketMenu_Trinket0")
	reskinButton("TrinketMenu_Trinket1")

	reskinFrame(TrinketMenu_MenuFrame)
	for i = 1, 30 do
		reskinButton("TrinketMenu_Menu"..i)
	end
end

function S:ERT()
	if not IsAddOnLoaded("EchoRaidTools") then return end

	local function reskinTab(tab)
		local bg = M.SetBD(tab)
		bg:SetInside(tab, 2, 2)

		tab:SetNormalTexture(0)
		tab:SetPushedTexture(0)
		tab:SetDisabledTexture(0)
		local hl = tab:GetHighlightTexture()
		hl:SetColorTexture(cr, cg, cb, .2)
		hl:SetInside(bg)
	end

	local function resetButtonBG(self)
		self.__button:GetScript("OnLeave")(self.__button)
	end

	S:RegisterSkin("Blizzard_EncounterJournal", function()
		local encounterInfo = EncounterJournal.encounter.info
		local ERTTab, ERTFrame

		for i = encounterInfo:GetNumChildren(), 1, -1 do
			if ERTTab and ERTFrame then break end

			local child = select(i, encounterInfo:GetChildren())
			if child.unSelected then
				ERTTab = child
			elseif child.scrollframe then
				ERTFrame = child
			end
		end

		reskinTab(ERTTab)
		M.ReskinScroll(ERTFrame.scrollframe.ScrollBar)

		local scrollChild = ERTFrame.scrollframe:GetScrollChild()

		hooksecurefunc(scrollChild, "SetHeight", function(self)
			for i = self:GetNumChildren(), 1, -1 do
				local header = select(i, self:GetChildren())
				if not header.styled then
					for i = 5, 19 do
						select(i, header.button:GetRegions()):SetTexture("")
					end
					M.Reskin(header.button)
					header.descriptionBG:SetAlpha(0)
					header.descriptionBGBottom:SetAlpha(0)
					header.description:SetTextColor(1, 1, 1)
					header.button.label:SetTextColor(1, 1, 1)
					header.button.label.SetTextColor = M.Dummy
					header.button.expandIcon:SetWidth(20) -- don't wrap the text
					header.button.waIconbg = M.ReskinIcon(header.button.waIcon)
					header.glowAnimation.__button = header.button
					header.glowAnimation:HookScript("OnPlay", resetButtonBG)

					header.styled = true
				end

				header.button.waIconbg:SetShown(header.button.waIcon:IsShown())
			end
		end)
	end)
end

function S:PSFJ()
	if not IsAddOnLoaded("ProtoformSynthesisFieldJournal") then return end

	local frame = _G.ProtoformSynthesisFieldJournal
	M.StripTextures(frame)
	M.SetBD(frame)

	M.ReskinClose(frame.CloseButton)
	M.ReskinTab(frame.PanelTabs.PetTab)
	M.ReskinTab(frame.PanelTabs.MountTab)
	M.ReskinTab(frame.PanelTabs.SettingsTab)

	local function handlePSFJScroll(scrollBar)
		M.ReskinScroll(scrollBar)
		S.ReskinScrollEnd(scrollBar.TopButton, "up")
		S.ReskinScrollEnd(scrollBar.BottomButton, "down")
	end

	frame.List.Background:Hide()
	handlePSFJScroll(frame.List.ScrollFrame.ScrollBar)
	frame.Settings.Background:Hide()
	handlePSFJScroll(frame.Settings.ScrollFrame.ScrollBar)

	local function onEnter(button)
		button.bg:SetBackdropBorderColor(0, .6, 1)
	end

	local function onLeave(button)
		button.bg:SetBackdropBorderColor(0, 0, 0)
	end

	hooksecurefunc(frame.List, "Update", function(self)
		local buttons = self.ScrollFrame.Buttons
		if buttons then
			for i = 1, #buttons do
				local button = buttons[i]
				if not button.styled then
					button:HideBackdrop()
					button.bg = M.CreateBDFrame(button, .25)
					button.bg:SetInside(nil, 2, 2)
					button:HookScript("OnEnter", onEnter)
					button:HookScript("OnLeave", onLeave)

					button.styled = true
				end
			end
		end
	end)

	local done
	hooksecurefunc(frame.Settings, "Update", function(self)
		if done then return end
		done = true

		local buttons = self.ScrollFrame.Buttons
		for i = 1, #buttons do
			local button = buttons[i]
			if button.CheckButton then
				M.ReskinCheck(button.CheckButton)
			end
		end
	end)
end

function S:TLDR()
	if not IsAddOnLoaded("TLDRMissions") then return end

	local function reskinUIElements(frame)
		for i = 1, frame:GetNumChildren() do
			local child = select(i, frame:GetChildren())
			if child:IsObjectType("CheckButton") then
				M.ReskinCheck(child)
				child:SetSize(24, 24)
			elseif child:IsObjectType("Button") then
				M.Reskin(child)
			elseif child:IsObjectType("Slider") then
				M.ReskinSlider(child)
			elseif child:IsObjectType("EditBox") then
				M.ReskinEditBox(child)
			elseif child:IsObjectType("Frame") and child.Button then
				M.StripTextures(child)
				M.ReskinArrow(child.Button, "down")
			end
		end
	end

	M.StripTextures(TLDRMissionsFrame)
	M.ReskinClose(TLDRMissionsFrame.CloseButton)
	M.SetBD(TLDRMissionsFrame):SetInside(nil, 2, 2)
	M.Reskin(TLDRMissionsToggleButton)

	reskinUIElements(TLDRMissionsFrameMainPanel)
	reskinUIElements(TLDRMissionsFrameAdvancedPanel)

	M.ReskinTab(TLDRMissionsFrameTab1)
	M.ReskinTab(TLDRMissionsFrameTab2)
	M.ReskinTab(TLDRMissionsFrameTab3)
end

local function handleJournal()
	local frame = ManuscriptsJournal
	if not frame or frame.styled then return end
	frame.styled = true

	local progressBar = frame.progressBar
	if progressBar then
		progressBar.border:Hide()
		progressBar:DisableDrawLayer("BACKGROUND")
		progressBar.text:SetPoint("CENTER", 0, 1)
		progressBar:SetStatusBarTexture(I.bdTex)
		M.CreateBDFrame(progressBar, 1)
	end

	M.StripTextures(frame.iconsFrame)
	M.CreateBDFrame(frame, 1)
	M.ReskinEditBox(frame.SearchBox)
	M.ReskinFilterButton(frame.FilterButton)
	M.ReskinArrow(frame.PagingFrame.PrevPageButton, "left")
	M.ReskinArrow(frame.PagingFrame.NextPageButton, "right")
	S:ReskinSecureTabs()
	if CollectionsJournalCoverTab then
		CollectionsJournalCoverTab:SetAlpha(0)
	end

	hooksecurefunc(frame, "UpdateButton", function(_, button)
		if button.iconTexture and not button.bg then
			local icon = button.iconTexture
			button.slotFrameCollected:SetTexture("")
			button.slotFrameUncollected:SetTexture("")
			button:SetPushedTexture(0)
			button:GetHighlightTexture():SetColorTexture(1, 1, 1, .25)
			button:GetHighlightTexture():SetAllPoints(icon)
			button.iconTextureUncollected:SetTexCoord(unpack(I.TexCoord))
			button.bg = M.ReskinIcon(icon)
		end
	end)
end

function S:ManuscriptsJournal()
	if IsAddOnLoaded("ManuscriptsJournal") then
		handleJournal()
	else
		local hooked
		S:RegisterSkin("Blizzard_Collections", function()
			if hooked then return end
			HeirloomsJournal:HookScript("OnShow", handleJournal)
			hooked = true
		end)
	end
end

function S:OtherSkins()
	if not R.db["Skins"]["BlizzardSkins"] then return end

	S:FriendGroups()
	C_Timer.After(1, S.PostalSkin)
	S:SoulbindsTalents()
	S:MRT_Skin()
	S:SoulshapeJournal()
	S:ATT()
	S:TrinketMenu()
	S:ERT()
	--S:PSFJ()
	S:TLDR()
	S:ManuscriptsJournal()
end