local _, addon = ...
local API = addon.API;
local L = addon.L;
local LandingPageUtil = addon.LandingPageUtil;
local AtlasUtil = addon.AtlasUtil;
local FactionUtil = addon.FactionUtil;


local ipairs = ipairs;
local CreateFrame = CreateFrame;
local C_Reputation = C_Reputation;
local C_MajorFactions = C_MajorFactions;


local FactionTab;
local FactionButtons = {};  --Can be created by other tab


local FACTION_BUTTON_SIZE = 80;
local FACTION_BUTTON_GAP_H = 20;
local FACTION_BUTTON_GAP_V = 20 + 8;
local SUBFACTION_BUTTON_SIZE = 40;


local function HideTooltip()
	GameTooltip:Hide();
end


local ReputationTooltipScripts = {};
do
	--Derivative of Blizzard ReputationUtil.lua

	function ReputationTooltipScripts.AppendClickInstruction(tooltip, factionID, asBottomLine)
		local text = (FactionUtil:IsFactionWatched(factionID) and L["Instruction Untrack Reputation"]) or L["Instruction Track Reputation"];
		if C_Reputation.IsMajorFaction(factionID) then
			text = L["Instruction Click To View Renown"].."\n"..text;
		end

		if asBottomLine then
			GameTooltip_SetBottomText(tooltip, text, GREEN_FONT_COLOR);
		else
			GameTooltip_AddColoredLine(tooltip, text, GREEN_FONT_COLOR, true);
		end
	end

	function ReputationTooltipScripts.TryAppendAccountReputationLineToTooltip(tooltip, factionID)
		if not tooltip or not factionID or not C_Reputation.IsAccountWideReputation(factionID) then
			return;
		end
		local wrapText = false;
		tooltip:AddLine(REPUTATION_TOOLTIP_ACCOUNT_WIDE_LABEL, 0.000, 0.800, 1.000, wrapText);  --ACCOUNT_WIDE_FONT_COLOR
	end

	function ReputationTooltipScripts.AppendProgressBar(tooltip, min, max, value)
		--GameTooltip_ShowProgressBar(tooltip, min, max, value, REPUTATION_PROGRESS_FORMAT:format(value, max));
		tooltip:AddLine(string.format("|cffffd100%s|r %d/%d", L["Progress Label"], value, max), 1, 1, 1, false);
	end

	function ReputationTooltipScripts.ShowMajorFactionRenownTooltip(self)
		--Before reaching Paragon
		local factionID = self.factionID;
		local data = C_MajorFactions.GetMajorFactionData(factionID);
		if not data then
			return;
		end

		local tooltip = GameTooltip;
		local callback = GenerateClosure(ReputationTooltipScripts.ShowMajorFactionRenownTooltip, self);

		tooltip:SetOwner(self, "ANCHOR_RIGHT");
		tooltip:SetText(data.name, 1, 1, 1);

		ReputationTooltipScripts.TryAppendAccountReputationLineToTooltip(tooltip, factionID);

		--GameTooltip_AddHighlightLine(tooltip, RENOWN_LEVEL_LABEL:format(data.renownLevel));
		local maxLevel = API.GetMaxRenownLevel(factionID);

		tooltip:AddLine(string.format("|cffffd100%s|r %d/%d", LANDING_PAGE_RENOWN_LABEL, data.renownLevel, maxLevel), 1, 1, 1);
		local value = data.renownReputationEarned;
		local threshold = data.renownLevelThreshold;
		ReputationTooltipScripts.AppendProgressBar(tooltip, 0, threshold, value);

		tooltip:AddLine(" ");
		--[[
		tooltip:AddLine(MAJOR_FACTION_RENOWN_TOOLTIP_PROGRESS:format(data.name), 1, 0.82, 0, true);
		tooltip:AddLine(" ");
		--]]

		local nextRenownRewards = C_MajorFactions.GetRenownRewardsForLevel(factionID, C_MajorFactions.GetCurrentRenownLevel(factionID) + 1);
		if #nextRenownRewards > 0 then
			RenownRewardUtil.AddRenownRewardsToTooltip(tooltip, nextRenownRewards, callback);
		end

		tooltip:AddLine(" ");
		ReputationTooltipScripts.AppendClickInstruction(tooltip, factionID);

		tooltip:Show();
	end

	function ReputationTooltipScripts.ShowParagonRewardsTooltip(self)
		local tooltip = GameTooltip;

		--AddParagonRewardsToTooltip
		local factionID = self.factionID;
		local factionStandingtext;
		local factionData = C_Reputation.GetFactionDataByID(factionID);
		local reputationInfo = C_GossipInfo.GetFriendshipReputation(factionID);
		if reputationInfo and reputationInfo.friendshipFactionID > 0 then
			factionStandingtext = reputationInfo.reaction;
		elseif C_Reputation.IsMajorFaction(factionID) then
			factionStandingtext = MAJOR_FACTION_MAX_RENOWN_REACHED;
		else
			local gender = UnitSex("player");
			factionStandingtext = GetText("FACTION_STANDING_LABEL"..factionData.reaction, gender);
		end
		local currentValue, threshold, rewardQuestID, hasRewardPending, tooLowLevelForParagon = C_Reputation.GetFactionParagonInfo(factionID);

		tooltip:SetOwner(self, "ANCHOR_RIGHT");
		tooltip:SetText(factionData.name);
		tooltip.factionID = factionID;
		ReputationTooltipScripts.TryAppendAccountReputationLineToTooltip(tooltip, factionID);

		if tooLowLevelForParagon then
			tooltip:AddLine(PARAGON_REPUTATION_TOOLTIP_TEXT_LOW_LEVEL, 1, 0.82, 0, true);
		else
			tooltip:AddLine(factionStandingtext, 1, 1, 1, true);

			if not hasRewardPending and currentValue and threshold then
				local value = math.fmod(currentValue, threshold);
				-- show overflow if reward is pending
				if hasRewardPending then
					value = value + threshold;
				end
				ReputationTooltipScripts.AppendProgressBar(tooltip, 0, threshold, value);
			end

			local description = PARAGON_REPUTATION_TOOLTIP_TEXT:format(factionData.name);
			if hasRewardPending then
				local questIndex = C_QuestLog.GetLogIndexForQuestID(rewardQuestID);
				local text = GetQuestLogCompletionText(questIndex);
				if text and text ~= "" then
					description = text;
				end
			end
			tooltip:AddLine(" ");
			tooltip:AddLine(description, 1, 0.82, 0, true);

			if rewardQuestID then
				--GameTooltip_AddQuestRewardsToTooltip(tooltip, rewardQuestID);
			end
		end

		tooltip:AddLine(" ");
		ReputationTooltipScripts.AppendClickInstruction(tooltip, factionID);

		tooltip:Show();
		--GameTooltip_OnShow(tooltip);    --Recalculating padding

		if rewardQuestID and not API.IsQuestRewardCached(rewardQuestID) then
			self.UpdateTooltip = self.ShowTooltip;
		else
			self.UpdateTooltip = nil;
		end
	end

	function ReputationTooltipScripts.ShowFriendshipReputationTooltip(self)
		local factionID = self.factionID;
		local friendshipData = C_GossipInfo.GetFriendshipReputation(factionID);
		if not friendshipData or friendshipData.friendshipFactionID < 0 then
			return
		end

		local tooltip = GameTooltip;

		tooltip:SetOwner(self, "ANCHOR_RIGHT");

		local rankInfo = C_GossipInfo.GetFriendshipReputationRanks(friendshipData.friendshipFactionID);
		if rankInfo.maxLevel > 0 then
			GameTooltip_SetTitle(tooltip, friendshipData.name.." ("..rankInfo.currentLevel.." / "..rankInfo.maxLevel..")", HIGHLIGHT_FONT_COLOR);
		else
			GameTooltip_SetTitle(tooltip, friendshipData.name, HIGHLIGHT_FONT_COLOR);
		end

		ReputationTooltipScripts.TryAppendAccountReputationLineToTooltip(tooltip, factionID);

		tooltip:AddLine(" ");
		tooltip:AddLine(friendshipData.text, nil, nil, nil, true);

		if friendshipData.nextThreshold then
			local current = friendshipData.standing - friendshipData.reactionThreshold;
			local max = friendshipData.nextThreshold - friendshipData.reactionThreshold;
			local wrapText = true;
			GameTooltip_AddHighlightLine(tooltip, friendshipData.reaction.." ("..current.." / "..max..")", wrapText);
		else
			local wrapText = true;
			GameTooltip_AddHighlightLine(tooltip, friendshipData.reaction, wrapText);
		end

		tooltip:AddLine(" ");

		if self.playerCompanionID and not InCombatLockdown() then  --Delves Companion Level
			GameTooltip_AddColoredLine(tooltip, L["Instruction Click To View Companion"], GREEN_FONT_COLOR, true);
		end

		ReputationTooltipScripts.AppendClickInstruction(tooltip, factionID);

		tooltip:Show();
	end

	function ReputationTooltipScripts.ShowStandardTooltip(self)
		local factionID = self.factionID;
		local factionData = factionID and API.GetReputationProgress(factionID);
		if not factionData then return end;

		local tooltip = GameTooltip;
		tooltip:SetOwner(self, "ANCHOR_RIGHT");

		tooltip:SetText(factionData.name, 1, 1, 1);

		ReputationTooltipScripts.TryAppendAccountReputationLineToTooltip(tooltip, factionID);

		tooltip:AddLine(API.GetReputationStandingText(factionData.reaction), 1, 1, 1, true);

		if not factionData.isFull then
			ReputationTooltipScripts.AppendProgressBar(tooltip, 0, factionData.maxValue, factionData.currentValue);
		end

		tooltip:AddLine(" ");
		ReputationTooltipScripts.AppendClickInstruction(tooltip, factionID);

		tooltip:Show();
	end
end


local CreateFactionIconButton;
do
	local FactionIconButtonMixin = {};

	function FactionIconButtonMixin:OnEnter()

	end

	function FactionIconButtonMixin:OnLeave()
		if not self.selected then

		end
	end

	function FactionIconButtonMixin:OnClick()
		if not self.selected then
			if FactionTab:DisplayMajorFactionDetail(self.factionID) then
				LandingPageUtil.PlayUISound("CheckboxOn");
			end
		end
	end

	function FactionIconButtonMixin:OnMouseDown()
		if not self.selected then
			self.FactionIcon:SetPoint("CENTER", self, "CENTER", 0, -1);
		end
	end

	function FactionIconButtonMixin:OnMouseUp()
		self.FactionIcon:SetPoint("CENTER", self, "CENTER", 0, 0);
	end

	function FactionIconButtonMixin:SetFaction(factionID)
		self.factionID = factionID;
		local data = C_MajorFactions.GetMajorFactionData(factionID);
		if data then
			AtlasUtil.SetFactionIcon(self.FactionIcon, factionID);
			AtlasUtil.SetFactionIconHighlight(self.Highlight, factionID);
			self.Highlight:SetAlpha(1);
			self.Highlight:SetVertexColor(1, 0.82, 0);
		end
	end

	function FactionIconButtonMixin:SetSelected(state)
		self.selected = state;
		if state then
			self.FactionIcon:SetVertexColor(1, 1, 1);
		else
			self.FactionIcon:SetVertexColor(0.5, 0.5, 0.5);
		end
	end

	function CreateFactionIconButton(parent)
		local f = CreateFrame("Button", nil, parent);
		f:SetSize(32, 32);
		f.FactionIcon = f:CreateTexture(nil, "OVERLAY");
		f.FactionIcon:SetPoint("CENTER", f, "CENTER", 0, 0);
		f.FactionIcon:SetSize(44, 44);

		f.Highlight = f:CreateTexture(nil, "HIGHLIGHT");
		f.Highlight:SetPoint("TOPLEFT", f.FactionIcon, "TOPLEFT", 0, 0);
		f.Highlight:SetPoint("BOTTOMRIGHT", f.FactionIcon, "BOTTOMRIGHT", 0, 0);

		API.Mixin(f, FactionIconButtonMixin);
		f:SetScript("OnEnter", f.OnEnter);
		f:SetScript("OnLeave", f.OnLeave);
		f:SetScript("OnClick", f.OnClick);
		f:SetScript("OnMouseDown", f.OnMouseDown);
		f:SetScript("OnMouseUp", f.OnMouseUp);

		return f
	end
end


local LandingPageMajorFactionButtonMixin = {};
do
	function LandingPageMajorFactionButtonMixin:OnLoad()
		local tex = "Interface/AddOns/Plumber/Art/ExpansionLandingPage/ExpansionLandingPage";

		self.Border:SetTexture(tex);
		self.Border:SetTexCoord(0/1024, 200/1024, 0/1024, 216/1024);

		self.BorderHighlight:SetTexture(tex);
		self.BorderHighlight:SetTexCoord(0/1024, 200/1024, 0/1024, 216/1024);

		self.Background:SetTexture(tex);
		self.Background:SetTexCoord(200/1024, 360/1024, 20/1024, 180/1024);

		self.Glow:SetTexture(tex);
		self.Glow:SetTexCoord(0/1024, 200/1024, 416/1024, 616/1024);

		local ProgressBar = self.ProgressBar;

		local lowTexCoords =
		{
			x = 360/1024,
			y = 20/1024,
		};
		local highTexCoords =
		{
			x = 520/1024,
			y = 180/1024,
		};

		ProgressBar:SetSwipeTexture(tex);
		ProgressBar:SetTexCoordRange(lowTexCoords, highTexCoords);
		ProgressBar:SetSwipeColor(56/255, 184/255, 255/255);

		ProgressBar.visualOffset = 0.06;
		API.Mixin(ProgressBar, addon.RadialProgressBarMixin);
		ProgressBar:SetValue(75, 100);

		self:SetScript("OnEnter", self.OnEnter);
		self:SetScript("OnLeave", self.OnLeave);
		self:SetScript("OnClick", self.OnClick);

		--self.AlertIcon:SetTexture("Interface/AddOns/Plumber/Art/ExpansionLandingPage/AlertIcon-Green");
	end

	function LandingPageMajorFactionButtonMixin:SetShowRenownLevel(state)
		if state and not (self.alwaysHideRenownLevel) then
			self.Level:Show();
			self.ProgressBar.visualOffset = 0.06;
			if self.isMinimized then
				self.BorderHighlight:SetTexCoord(544/1024, 672/1024, 0/1024, 128/1024);
				self.Border:SetTexCoord(544/1024, 672/1024, 0/1024, 128/1024);
				self.Border:SetSize(64, 64);
			else
				self.BorderHighlight:SetTexCoord(0/1024, 200/1024, 0/1024, 216/1024);
				self.Border:SetTexCoord(0/1024, 200/1024, 0/1024, 216/1024);
				self.Border:SetSize(100, 108);
			end
		else
			self.Level:Hide();
			self.ProgressBar.visualOffset = 0.02;
			if self.isMinimized then
				self.BorderHighlight:SetTexCoord(544/1024, 672/1024, 128/1024, 256/1024);
				self.Border:SetTexCoord(544/1024, 672/1024, 128/1024, 256/1024);
				self.Border:SetSize(64, 64);
			else
				self.BorderHighlight:SetTexCoord(0/1024, 200/1024, 216/1024, 416/1024);
				self.Border:SetTexCoord(0/1024, 200/1024, 216/1024, 416/1024);
				self.Border:SetSize(100, 100);
			end
		end
	end

	function LandingPageMajorFactionButtonMixin:Refresh()
		local factionID = self.factionID;
		if not factionID then return end;

		local progress = API.GetReputationProgress(factionID);

		if progress then
			self.reputationType = progress.reputationType;
			local currentValue, maxValue;
			if progress.isFull then
				local paragonLevel;
				currentValue, maxValue, paragonLevel = API.GetParagonValuesAndLevel(factionID);
				self:SetShowRenownLevel(false);
			else
				self.Level:SetText(progress.level);
				currentValue, maxValue = progress.currentValue, progress.maxValue;
				self:SetShowRenownLevel(true);
			end

			if progress.rewardPending then
				self.Glow:Show();
				self.Glow.AnimGlow:Play();
				self.ProgressBar:SetValue(100, 100);
				self.AlertIcon:Show();
			else
				self.Glow:Hide();
				self.Glow.AnimGlow:Stop();
				self.ProgressBar:SetValue(currentValue, maxValue);
				self.AlertIcon:Hide();
			end

			if progress.isUnlocked then

			else

			end

			if self.elementData then
				self.elementData.name = progress.name;
			end
		else
			self.reputationType = 0;
		end


		--debug
		--[[
		self.Level:SetText(6);
		self:SetShowRenownLevel(true);
		self.ProgressBar:SetValue(66, 100);
		self.Glow:Hide();
		--]]
	end

	function LandingPageMajorFactionButtonMixin:SetParentFactionID(parentFactionID)
		self.parentFactionID = parentFactionID;
	end

	function LandingPageMajorFactionButtonMixin:SetVisualByFaction(factionID)
		local data = C_MajorFactions.GetMajorFactionData(factionID);
		local r, g, b = 1, 1, 1;

		if data then
			AtlasUtil.SetFactionIcon(self.FactionIcon, factionID);
		end

		if factionID or self.parentFactionID then
			r, g, b = FactionUtil:GetProgressBarColor(factionID, self.parentFactionID);
		end

		self.ProgressBar:SetSwipeColor(r, g, b);
	end

	function LandingPageMajorFactionButtonMixin:SetFaction(factionID)
		self.factionID = factionID;
		self:SetVisualByFaction(factionID);
		self:Refresh();
		--For Blizzard Mixin
		self.elementData = {
			factionID = factionID,
		};
	end

	function LandingPageMajorFactionButtonMixin:OnEnter()
		self:ShowTooltip();
	end

	function LandingPageMajorFactionButtonMixin:OnLeave()
		HideTooltip();
	end

	function LandingPageMajorFactionButtonMixin:OnClick(button)
		if self.onClickFunc then
			self.onClickFunc(self, button);
		end
	end

	function LandingPageMajorFactionButtonMixin:ShowTooltip()
		--See Blizzard_UIPanels_Game/ReputationFrame.lua
		self.UpdateTooltip = nil;

		if C_Reputation.IsFactionParagonForCurrentPlayer(self.factionID) then
			ReputationTooltipScripts.ShowParagonRewardsTooltip(self);
		elseif self.reputationType == 2 then    --Friendship
			ReputationTooltipScripts.ShowFriendshipReputationTooltip(self);
		elseif self.reputationType == 3 then    --MajorFaction
			ReputationTooltipScripts.ShowMajorFactionRenownTooltip(self);
		elseif self.reputationType == 1 then    --Standard
			ReputationTooltipScripts.ShowStandardTooltip(self);
		end
	end

	function LandingPageMajorFactionButtonMixin:SetMinimized(state)
		self.isMinimized = state;
		local lowTexCoords, highTexCoords;
		if self.isMinimized then
			--Subfaction
			self:SetSize(SUBFACTION_BUTTON_SIZE, SUBFACTION_BUTTON_SIZE);
			self.Border:ClearAllPoints();
			self.Border:SetPoint("CENTER", self, "CENTER", 0, 0);
			self.Border:SetSize(64, 64);
			self.Glow:SetSize(96, 96);
			self.AlertIcon:SetSize(24, 24);
			self.Level:SetPoint("CENTER", self, "CENTER", 0, -16);
			self.Level:SetFontObject("GameFontNormalSmall");
			self.FactionIcon:SetSize(30, 30);
			self.Background:SetSize(64, 64);
			self.Background:SetTexCoord(672/1024, 800/1024, 0/1024, 128/1024);
			self.ProgressBar:SetSize(38, 38);
			self.FactionIcon:SetDrawLayer("BACKGROUND", 1);
			lowTexCoords = {x = 824/1024, y = 24/1024};
			highTexCoords = {x = 904/1024, y = 104/1024};
		else
			--Major Faction
			self:SetSize(FACTION_BUTTON_SIZE, FACTION_BUTTON_SIZE);
			self.Border:ClearAllPoints();
			self.Border:SetPoint("TOP", self, "TOP", 0, 10);
			self.Border:SetSize(100, 108);
			self.Glow:SetSize(200, 200);
			self.AlertIcon:SetSize(32, 32);
			self.Level:SetPoint("CENTER", self, "CENTER", 0, -33);
			self.Level:SetFontObject("GameFontNormal");
			self.FactionIcon:SetSize(56, 56);
			self.Background:SetSize(80, 80);
			self.Background:SetTexCoord(200/1024, 360/1024, 20/1024, 180/1024);
			self.ProgressBar:SetSize(80, 80);
			self.FactionIcon:SetDrawLayer("OVERLAY", 0);
			lowTexCoords = {x = 360/1024, y = 20/1024};
			highTexCoords = {x = 520/1024, y = 180/1024};
		end
		self.ProgressBar:SetTexCoordRange(lowTexCoords, highTexCoords);
	end

	function LandingPageMajorFactionButtonMixin:SetIconByFileID(fileID)
		self.FactionIcon:SetTexture(fileID);
	end

	function LandingPageMajorFactionButtonMixin:SetIconByCreatureDisplayID(creatureDisplayID)
		SetPortraitTextureFromCreatureDisplayID(self.FactionIcon, creatureDisplayID);
	end
end


local function FactionButton_OnClickFunc(self, button)
	if button == "LeftButton" and IsShiftKeyDown() then
		local newState = not FactionUtil:IsFactionWatched(self.factionID);
		local watchedFactionID = (newState and self.factionID) or 0;
		C_Reputation.SetWatchedFactionByID(watchedFactionID);       --Trigger UPDATE_FACTION
		HideTooltip();

		if newState then
			LandingPageUtil.PlayUISound("CheckboxOn");
		else
			LandingPageUtil.PlayUISound("CheckboxOff");
		end

		return
	end

	if FactionTab then
		if FactionTab:DisplayMajorFactionDetail(self.factionID) then
			LandingPageUtil.PlayUISound("PageOpen");
			return
		end
	end

	if self.playerCompanionID and not InCombatLockdown() then
		local f = DelvesCompanionConfigurationFrame;
		if not f:IsShown() then
			f.playerCompanionID = self.playerCompanionID;
			ShowUIPanel(f);
		else
			HideUIPanel(f);
		end
	end
end

local function CreateFactionButton(parent, clickable)
	local f = CreateFrame("Button", nil, parent, "PlumberLandingPageMajorFactionButtonTemplate");
	API.Mixin(f, LandingPageMajorFactionButtonMixin);
	f:OnLoad();
	table.insert(FactionButtons, f);

	if clickable then
		f.onClickFunc = FactionButton_OnClickFunc;
	end

	return f
end
LandingPageUtil.CreateFactionButton = CreateFactionButton;


local CreateRenownItemButton;
do
	local RenownItemButtonMixin = {};

	function RenownItemButtonMixin:GreyOut(state)
		if state then
			self.RewardIcon:SetDesaturated(true);
			self.RewardIcon:SetVertexColor(0.8, 0.8, 0.8);
			self.Name:SetTextColor(0.6, 0.6, 0.6);
		else
			self.RewardIcon:SetDesaturated(false);
			self.RewardIcon:SetVertexColor(1, 1, 1);
			self.Name:SetTextColor(0.922, 0.871, 0.761);
		end
	end

	function RenownItemButtonMixin:SetRewardInfo(info)
		self.RewardIcon:SetTexture(info.icon);
		self.Name:SetText(info.name);
		self.name = info.name;
		self.description = info.description;
		self.isAccountUnlock = info.isAccountUnlock;
		self:GreyOut(self.locked);

		--The following fields always seem to be nil
		self.type, self.id = nil, nil;
		if info.itemID then
			self.type = "item";
			self.id = info.itemID;
		elseif info.spellID then
			self.type = "spell";
			self.id = info.spellID;
		elseif info.mountID then
			self.type = "mount";
			self.id = info.mountID;
		elseif info.transmogID then
			self.type = "transmog";
			self.id = info.transmogID;
		elseif info.transmogSetID then
			self.type = "transmogSet";
			self.id = info.transmogSetID;
		elseif info.transmogIllusionSourceID then
			self.type = "illusion";
			self.id = info.transmogIllusionSourceID;
		elseif info.titleMaskID then
			self.type = "title";
			self.id = info.titleMaskID;
		end
	end

	function RenownItemButtonMixin:OnEnter()
		FactionTab:HighlightButton(self);

		local tooltip = GameTooltip;
		tooltip:SetOwner(self, "ANCHOR_RIGHT");
		tooltip:SetText(self.name, 1, 1, 1);
		if self.isAccountUnlock then
			tooltip:AddLine(RENOWN_REWARD_ACCOUNT_UNLOCK_LABEL, 0.000, 0.800, 1.000, true);  --ACCOUNT_WIDE_FONT_COLOR
			tooltip:AddLine(" ");
		end
		tooltip:AddLine(self.description, 1, 0.82, 0, true);
		tooltip:Show();

		if not self.locked then
			self.Name:SetTextColor(1, 1, 1);
		end
	end

	function RenownItemButtonMixin:OnLeave()
		FactionTab:HighlightButton(nil);
		HideTooltip();
		self:GreyOut(self.locked);
	end

	function CreateRenownItemButton(parent)
		local f = CreateFrame("Button", nil, parent);
		f:SetSize(256, 32);

		f.RewardIcon = f:CreateTexture(nil, "ARTWORK");
		f.RewardIcon:SetSize(30, 30);
		f.RewardIcon:SetPoint("LEFT", f, "LEFT", 2, 0);
		f.RewardIcon:SetTexCoord(0.0625, 0.9375, 0.0625, 0.9375);

		local mask = f:CreateMaskTexture(nil, "ARTWORK");
		mask:SetSize(32, 32);
		mask:SetPoint("CENTER", f.RewardIcon, "CENTER", 0, 0);
		mask:SetTexture("Interface/AddOns/Plumber/Art/BasicShape/Mask-Chamfer.tga", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE");
		f.RewardIcon:AddMaskTexture(mask);

		f.ItemBorder = f:CreateTexture(nil, "OVERLAY");
		f.ItemBorder:SetSize(40, 40);
		f.ItemBorder:SetPoint("CENTER", f.RewardIcon, "CENTER", 0, 0);
		f.ItemBorder:SetTexture("Interface/AddOns/Plumber/Art/ExpansionLandingPage/ItemBorder");
		f.ItemBorder:SetTexCoord(80/512, 160/512, 0/512, 80/512);
		API.DisableSharpening(f.ItemBorder);

		f.Name = f:CreateFontString(nil, "OVERLAY", "GameFontNormal");
		f.Name:SetPoint("LEFT", f, "LEFT", 40, 0);
		f.Name:SetJustifyH("LEFT");
		f.Name:SetTextColor(0.92, 0.92, 0.92);
		f.Name:SetMaxLines(2);
		f.Name:SetWidth(216);

		API.Mixin(f, RenownItemButtonMixin);
		f:SetScript("OnEnter", f.OnEnter);
		f:SetScript("OnLeave", f.OnLeave);

		return f
	end
end


local FactionTabMixin = {};
do
	local DynamicEvents = {
		"UPDATE_FACTION",
		"MAJOR_FACTION_RENOWN_LEVEL_CHANGED",
		"MAJOR_FACTION_UNLOCKED",
		"QUEST_TURNED_IN",
		"GLOBAL_MOUSE_UP",
	};

	function FactionTabMixin:Refresh()
		local focus = self:IsMouseOver() and API.GetMouseFocus();

		self.factionDirty = nil;
		for _, button in ipairs(FactionButtons) do
			if button.factionID then
				button:Refresh();
				if button == focus then
					if button:IsMouseMotionFocus() and button.onClickFunc then
						button:OnEnter();
					end
				end
			end
		end

		self:UpdateLeftWidgets();
	end

	function FactionTabMixin:GetFactionButtonByID(factionID)
		for _, button in ipairs(FactionButtons) do
			if factionID == button.factionID then
				return button
			end
		end
	end

	function FactionTabMixin:OnShow()
		if self.isLayoutDirty then
			FactionTab:OnLayoutChanged();
		end
		self:Refresh();
		API.RegisterFrameForEvents(self, DynamicEvents);
		LandingPageUtil.ShowLeftFrame(self.isOverview);
		if self:IsViewingFactionDetail() then
			self:UpdateRewardsList(true);
		end
	end

	function FactionTabMixin:OnHide()
		self.t = nil;
		self:SetScript("OnUpdate", nil);
		API.UnregisterFrameForEvents(self, DynamicEvents);
		self:StopAnimating();
	end

	function FactionTabMixin:OnEvent(event, ...)
		if event == "UPDATE_FACTION" or event == "QUEST_TURNED_IN" or event == "MAJOR_FACTION_RENOWN_LEVEL_CHANGED" or event == "MAJOR_FACTION_UNLOCKED" then
			local updateRewards = event == "MAJOR_FACTION_RENOWN_LEVEL_CHANGED" or event == "MAJOR_FACTION_UNLOCKED";
			self:RequestFullUpdate(updateRewards);
		elseif event == "GLOBAL_MOUSE_UP" then
			local button = ...
			if button == "RightButton" and self:IsMouseOver() and not self.isOverview then
				self:DisplayOverview();
				LandingPageUtil.PlayUISound("PageClose");
			end
		end
	end

	function FactionTabMixin:OnUpdate(elapsed)
		self.t = self.t + elapsed;
		if self.t >= 0.2 then
			self.t = nil;
			self:SetScript("OnUpdate", nil);

			if self.factionDirty then
				self.factionDirty = nil;
				self:Refresh();
			end

			if self.rewardsDirty then
				self.rewardsDirty = nil;
				if self:IsViewingFactionDetail() then
					local retainPosition = true;
					self:UpdateRewardsList(retainPosition);
				end
			end
		end
	end

	function FactionTabMixin:RequestFullUpdate(updateRewards)
		self.factionDirty = true;
		if updateRewards then
			self.rewardsDirty = true;
		end
		self.t = 0;
		self:SetScript("OnUpdate", self.OnUpdate);
	end

	function FactionTabMixin:DisplayOverview()
		if self.isOverview then return end;

		self.isOverview = true;
		self.selectedFactionID = nil;
		LandingPageUtil.ShowLeftFrame(true);
		self.OverviewFrame:Show();
		if self.DetailFrame then
			self.DetailFrame:Hide();
		end
	end

	function FactionTabMixin:DisplayMajorFactionDetail(factionID)
		if not C_Reputation.IsMajorFaction(factionID) then return false end;

		self.isOverview = false;
		self.selectedFactionID = factionID;
		LandingPageUtil.ShowLeftFrame(false);
		self.OverviewFrame:Hide();
		self:InitDetailFrame();
		self.DetailFrame:Show();
		self:UpdateLeftWidgets();
		self:UpdateRightSection();

		return true
	end

	function FactionTabMixin:IsViewingFactionDetail()
		return not self.isOverview
	end

	function FactionTabMixin:InitDetailFrame()
		if self.DetailFrame then return end;

		local DetailFrame = CreateFrame("Frame", nil, self);
		self.DetailFrame = DetailFrame;
		DetailFrame:SetPoint("TOPLEFT", self, "TOPLEFT", 8, -8);
		DetailFrame:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -8, 8);
		--DetailFrame:SetHyperlinksEnabled(true);


		do  --LeftSection
			local LeftFrame = PlumberExpansionLandingPage.LeftSection;
			local LeftHeader = LandingPageUtil.CreateListCategoryButton(DetailFrame, MAJOR_FACTION_LIST_TITLE);
			LeftHeader:SetPoint("TOP", LeftFrame, "TOP", 0, -16);

			local ProgressDisplay = CreateFactionButton(DetailFrame);
			self.LeftProgressDisplay = ProgressDisplay;
			ProgressDisplay.alwaysHideRenownLevel = true;
			ProgressDisplay:SetShowRenownLevel(false);
			ProgressDisplay:SetPoint("TOP", LeftFrame, "TOP", 0, -72);
			ProgressDisplay:SetScale(1.25);
			ProgressDisplay:EnableMouse(false);
			ProgressDisplay:EnableMouse(false);

			local BackgroundGlow = DetailFrame:CreateTexture(nil, "BACKGROUND");
			BackgroundGlow:SetSize(256, 256);
			BackgroundGlow:SetPoint("CENTER", ProgressDisplay, "CENTER", 0, 0);
			BackgroundGlow:SetTexture("Interface/AddOns/Plumber/Art/ExpansionLandingPage/ExpansionLandingPage-BackgroundGlow");
			BackgroundGlow:SetBlendMode("ADD");
			local shrink = 48;
			BackgroundGlow:SetTexCoord(shrink/256, 1-shrink/256, shrink/256, 1-shrink/256);
			BackgroundGlow:SetVertexColor(51/255, 29/255, 17/255);


			--Create texts below LeftProgressDisplay (FactionName, Level, Rep until next level)
			local textWidth = 224;
			local textFonts = {
				"PlumberFont_16", "GameFontNormal", "GameFontNormal";
			};

			local fs, r, g, b;
			for i = 1, 3 do
				fs = DetailFrame:CreateFontString(nil, "OVERLAY", textFonts[i]);
				ProgressDisplay["Text"..i] = fs;
				fs:SetWidth(textWidth);
				fs:SetJustifyH("CENTER");
				fs:SetJustifyV("TOP");
				if i == 1 then
					--Faction Name
					fs:SetPoint("TOP", ProgressDisplay, "BOTTOM", 0, -24);
					fs:SetSpacing(2);
					r, g, b = 0.906, 0.737, 0.576;

					--Mouseover faction name to show faction description
					local LeftNameArea = CreateFrame("Frame", nil, DetailFrame);
					self.LeftNameArea = LeftNameArea;
					LeftNameArea:SetPoint("TOPLEFT", fs, "TOPLEFT", 0, 4);
					LeftNameArea:SetPoint("BOTTOMRIGHT", fs, "BOTTOMRIGHT", 0, -4);
					LeftNameArea:SetScript("OnEnter", function()
						local factionID = self.selectedFactionID;
						local factionData = factionID and C_Reputation.GetFactionDataByID(factionID);
						if factionData and factionData.description then
							local tooltip = GameTooltip;
							tooltip:SetOwner(LeftNameArea, "ANCHOR_RIGHT");
							tooltip:SetText(factionData.name, 1, 1, 1);
							tooltip:AddLine(factionData.description, 1, 0.82, 0, true);
							tooltip:Show();
						end
					end);
					LeftNameArea:SetScript("OnLeave", function()
						HideTooltip();
					end);
				else
					fs:SetPoint("TOP", ProgressDisplay["Text"..(i - 1)], "BOTTOM", 0, -6);
					if i == 2 then
						r, g, b = 0.8, 0.8, 0.8;
					else
						r, g, b = 0.5, 0.5, 0.5;
					end
				end
				fs:SetTextColor(r, g, b);
			end


			self:UpdateFactionSelect();
		end


		do  --RightSection
			local RenownItemScrollView = API.CreateScrollView(DetailFrame);
			self.RenownItemScrollView = RenownItemScrollView;
			RenownItemScrollView:SetAllPoints(true);
			RenownItemScrollView:OnSizeChanged();
			RenownItemScrollView:SetStepSize(48);
			RenownItemScrollView:SetBottomOvershoot(48);
			RenownItemScrollView:EnableMouseBlocker(true);

			local ButtonHighlight = LandingPageUtil.CreateButtonHighlight(RenownItemScrollView);
			ButtonHighlight:SetSize(288, 36);

			function self:HighlightButton(renownItemButton)
				ButtonHighlight:Hide();
				ButtonHighlight:ClearAllPoints();
				if renownItemButton then
					ButtonHighlight:SetParent(renownItemButton);
					ButtonHighlight:SetPoint("CENTER", renownItemButton, "CENTER", 0, 0);
					ButtonHighlight:Show();
				end
			end

			local function ShowFocusedButtonTooltip()

			end
			RenownItemScrollView:SetOnScrollStopCallback(ShowFocusedButtonTooltip);


			local function RenownItemButton_Create()
				return CreateRenownItemButton(RenownItemScrollView)
			end

			local function RenownItemButton_OnRemoved(button)
				button.name = nil;
				button.description = nil;
				button.isAccountUnlock = nil;
				button.type = nil;
				button.id = nil;
			end

			RenownItemScrollView:AddTemplate("Item", RenownItemButton_Create, nil, RenownItemButton_OnRemoved);


			local function Divider_Create()
				local divider = RenownItemScrollView:CreateTexture(nil, "ARTWORK");
				divider:SetSize(512, 16);
				divider:SetTexture("Interface/AddOns/Plumber/Art/ExpansionLandingPage/Divider-H-Shadow");
				divider:SetAlpha(0.1);
				return divider
			end

			RenownItemScrollView:AddTemplate("Divider", Divider_Create);


			local function LevelText_Create()
				local fs = RenownItemScrollView:CreateFontString(nil, "OVERLAY", "PlumberFont_16");
				fs:SetTextColor(1, 1, 1, 0.2);
				fs:SetJustifyH("RIGHT");
				return fs
			end

			RenownItemScrollView:AddTemplate("LevelText", LevelText_Create);
		end


		addon.CallbackRegistry:Register("LandingPage.ExpansionChanged", function(expansionID)
			if DetailFrame:IsVisible() then
				FactionTab:DisplayOverview();
			end
		end);
	end

	function FactionTabMixin:UpdateLeftWidgets()
		if not (self.LeftProgressDisplay and self.selectedFactionID) then return end;

		local ProgressDisplay = self.LeftProgressDisplay;
		local factionID = self.selectedFactionID;
		local progress = API.GetReputationProgress(factionID);

		ProgressDisplay:SetVisualByFaction(factionID);

		if progress then
			local currentValue, maxValue;

			ProgressDisplay.Text1:SetText(progress.name);

			if progress.isFull then
				local paragonLevel;
				currentValue, maxValue, paragonLevel = API.GetParagonValuesAndLevel(factionID);
				ProgressDisplay.Text2:SetText(L["Paragon Reputation"]);
			else
				local maxLevel = API.GetMaxRenownLevel(factionID);
				currentValue, maxValue = progress.currentValue, progress.maxValue;
				ProgressDisplay.Text2:SetText(string.format("%s %d/%d", LANDING_PAGE_RENOWN_LABEL, progress.level, maxLevel))
			end

			if progress.rewardPending then
				ProgressDisplay.ProgressBar:SetValue(100, 100);
				ProgressDisplay.Text3:SetText(L["Reward Available"]);
				ProgressDisplay.Text3:SetTextColor(0.098, 1.000, 0.098);
			else
				ProgressDisplay.ProgressBar:SetValue(currentValue, maxValue);
				local nextLevelFormat = progress.isFull and L["Until Paragon Reward Format"] or L["Until Next Level Format"];
				ProgressDisplay.Text3:SetText(nextLevelFormat:format(maxValue - currentValue));
				ProgressDisplay.Text3:SetTextColor(0.5, 0.5, 0.5);
			end
		end

		if self.factionIconButtonPool then
			for _, button in self.factionIconButtonPool:EnumerateActive() do
				button:SetSelected(button.factionID == factionID);
			end
		end
	end

	function FactionTabMixin:UpdateRewardsList(retainPosition, scrollToFirstLockedReward)
		local factionID = self.selectedFactionID;
		local renownLevelsInfo = C_MajorFactions.GetRenownLevels(factionID);
		local rewards;

		local function SortFunc_UIOrder(a, b)
			if a.uiOrder and b.uiOrder and (a.uiOrder ~= b.uiOrder) then
				return a.uiOrder < b.uiOrder
			else
				return a.name < b.name
			end
		end

		local content = {};
		local n = 0;
		local gapSameTie = 8;
		local offsetY = 16;
		local buttonHeight = 32;
		local numLevels = #renownLevelsInfo;
		local top, bottom;
		local lastUnlockedIndex;
		local firstLockedIndex;

		if renownLevelsInfo then
			for k, v in ipairs(renownLevelsInfo) do
				rewards = C_MajorFactions.GetRenownRewardsForLevel(factionID, v.level)
				table.sort(rewards, SortFunc_UIOrder);

				if (not v.locked) and (not firstLockedIndex) then
					lastUnlockedIndex = n;
				end

				for index, rewardInfo in ipairs(rewards) do
					n = n + 1;
					top = offsetY;
					bottom = offsetY + buttonHeight + gapSameTie;
					content[n] = {
						dataIndex = n,
						templateKey = "Item",
						setupFunc = function(obj)
							obj.locked = v.locked;
							obj:SetRewardInfo(rewardInfo);
						end,
						top = top,
						bottom = bottom,
					};

					if v.locked and (not firstLockedIndex) then
						firstLockedIndex = n - 1;
					end

					if index == 1 then
						n = n + 1;
						top = offsetY + 0.5*(#rewards*(buttonHeight + gapSameTie) - gapSameTie);
						content[n] = {
							dataIndex = n,
							templateKey = "LevelText",
							setupFunc = function(obj)
								obj:SetText(v.level);
								if v.locked then
									obj:SetAlpha(0.2);
								else
									obj:SetAlpha(0.6);
								end
							end,
							top = top,
							bottom = top + 16,
							offsetX = -164,
							point = "CENTER",
						};
					end

					offsetY = bottom;
				end

				if k ~= numLevels then
					n = n + 1;
					top = offsetY;
					bottom = offsetY + 16 + 1*gapSameTie;
					content[n] = {
						dataIndex = n,
						templateKey = "Divider",
						top = top,
						bottom = bottom,
					};
					offsetY = bottom;
				end
			end
		end

		self.RenownItemScrollView:SetContent(content, retainPosition);

		if scrollToFirstLockedReward then
			self.RenownItemScrollView:SnapToContent(lastUnlockedIndex or n);
		end
	end

	function FactionTabMixin:UpdateRightSection()
		self:UpdateRewardsList(false, true);
	end

	function FactionTabMixin:UpdateFactionSelect()
		if not self.DetailFrame then return end;

		if self.factionIconButtonPool then
			self.factionIconButtonPool:ReleaseAll();
		else
			local function FactionIconButton_Create()
				return CreateFactionIconButton(self.DetailFrame);
			end

			local function FactionButton_OnRemove(obj)
				obj.playerCompanionID = nil;
			end

			self.factionIconButtonPool = LandingPageUtil.CreateObjectPool(FactionIconButton_Create, nil, FactionButton_OnRemove);
		end

		local button;
		local gap = 0;
		local iconButtonSize = 42;
		local iconsPerRow = 5;
		local factionList = {};
		local LeftFrame = PlumberExpansionLandingPage.LeftSection;

		for row, rowInfo in ipairs(FactionUtil.ActiveFactionLayout) do
			for _, factionInfo in ipairs(rowInfo) do
				if not factionInfo.shownAsSubfaction then
					table.insert(factionList, factionInfo.factionID);
				end
			end
		end

		local numFactions = #factionList;
		local numRows = math.ceil(numFactions / iconsPerRow);
		local iconsLastRow = numFactions + (1 - numRows) * iconsPerRow;
		local spanLastRow = iconsLastRow * (iconButtonSize + gap) - gap;
		local spanFullRow = iconsPerRow * (iconButtonSize + gap) - gap;
		local row, col = 1, 0;
		local fromY = 416;  --432
		local offsetX, spanX;

		for i, factionID in ipairs(factionList) do
			button = self.factionIconButtonPool:Acquire();
			button:SetSize(iconButtonSize, iconButtonSize);
			col = col + 1;
			if col > iconsPerRow then
				col = 1;
				row = row + 1;
				fromY = fromY + iconButtonSize + gap;
			end
			if row >= numRows then
				spanX = spanLastRow;
			else
				spanX = spanFullRow;
			end
			offsetX = -0.5 * spanX + (col - 1) * (iconButtonSize + gap);
			button:SetPoint("TOPLEFT", LeftFrame, "TOP", offsetX, -fromY);
			button:SetFaction(factionID);
		end
	end

	function FactionTabMixin:OnLayoutChanged()
		self.isLayoutDirty = nil;
		self.factionButtonPool:ReleaseAll();

		local index = 0;
		local offsetX;
		local offsetY = 0;
		local maxSpanX = 0;
		local maxSpanY = #FactionUtil.ActiveFactionLayout * (FACTION_BUTTON_SIZE + FACTION_BUTTON_GAP_V) - FACTION_BUTTON_GAP_V;

		for row, rowInfo in ipairs(FactionUtil.ActiveFactionLayout) do
			offsetX = 0;
			for _, factionInfo in ipairs(rowInfo) do
				index = index + 1;
				local f = self.factionButtonPool:Acquire();
				local majorFactionID = factionInfo.factionID;

				f:ClearAllPoints();
				if factionInfo.shownAsSubfaction then
					f:SetMinimized(true);
					local childOffsetY = offsetY - 0.5 * (FACTION_BUTTON_SIZE - SUBFACTION_BUTTON_SIZE);
					f:SetPoint("TOPRIGHT", self.OverviewFrame, "TOPRIGHT", 0, childOffsetY);
				else
					f:SetMinimized(false);
					f:SetPoint("TOPLEFT", self.OverviewFrame, "TOPLEFT", offsetX, offsetY);
				end

				f:SetFaction(majorFactionID);

				if factionInfo.shownAsSubfaction then
					f:SetIconByFileID(factionInfo.iconFileID);
				end

				if factionInfo.subFactions then
					offsetX = offsetX + FACTION_BUTTON_SIZE + 0.5 * FACTION_BUTTON_GAP_H;
					local childOffsetY = offsetY - 0.5 * (FACTION_BUTTON_SIZE - SUBFACTION_BUTTON_SIZE);
					for _, v in ipairs(factionInfo.subFactions) do
						local widget = self.factionButtonPool:Acquire();
						widget:SetMinimized(true);
						widget:ClearAllPoints();
						widget:SetPoint("TOPLEFT", self.OverviewFrame, "TOPLEFT", offsetX, childOffsetY);
						offsetX = offsetX + 0.5 * (FACTION_BUTTON_SIZE + FACTION_BUTTON_GAP_H);
						widget:SetParentFactionID(majorFactionID);
						widget:SetFaction(v.factionID);
						widget.playerCompanionID = v.playerCompanionID;
						if v.creatureDisplayID then
							widget:SetIconByCreatureDisplayID(v.creatureDisplayID);
						else
							widget:SetIconByFileID(v.iconFileID);
						end
					end
					offsetX = offsetX + 0.5 * FACTION_BUTTON_GAP_H;
				else
					offsetX = offsetX + (FACTION_BUTTON_SIZE + FACTION_BUTTON_GAP_H);
				end
			end

			local spanX = offsetX - FACTION_BUTTON_GAP_H;
			if spanX > maxSpanX then
				maxSpanX = spanX;
			end

			offsetY = offsetY - (FACTION_BUTTON_SIZE + FACTION_BUTTON_GAP_V);
		end

		local TabContainer = self:GetParent();
		self.OverviewFrame:ClearAllPoints();
		self.OverviewFrame:SetSize(maxSpanX, maxSpanY);
		self.OverviewFrame:SetPoint("TOPLEFT", TabContainer, "TOPLEFT", 0.5*(TabContainer:GetWidth() - maxSpanX), -0.5*(TabContainer:GetHeight() - maxSpanY));

		self:UpdateFactionSelect();
	end
end


local function CreateFactionTab(factionTab)
	--local majorFactionIDs = C_MajorFactions.GetMajorFactionIDs(10);

	API.Mixin(factionTab, FactionTabMixin);
	FactionTab = factionTab;
	factionTab:SetScript("OnShow", factionTab.OnShow);
	factionTab:SetScript("OnHide", factionTab.OnHide);
	factionTab:SetScript("OnEvent", factionTab.OnEvent);

	local OverviewFrame = CreateFrame("Frame", nil, factionTab);
	factionTab.OverviewFrame = OverviewFrame;
	factionTab.isOverview = true;


	local function FactionButton_Create()
		return CreateFactionButton(OverviewFrame, true);
	end

	local function FactionButton_OnRemove(f)
		f.factionID = nil;
		f.FactionIcon:SetTexCoord(0, 1, 0, 1);
		f.FactionIcon:SetTexture(nil);
	end

	FactionTab.factionButtonPool = LandingPageUtil.CreateObjectPool(FactionButton_Create, nil, FactionButton_OnRemove);


	FactionTab:OnLayoutChanged();
end

local function NotificationCheck(asTooltip)
	local viewedExpansionOnly = true;
	if asTooltip then
		local factionIDs = FactionUtil:GetFactionsWithRewardPending(viewedExpansionOnly);
		if factionIDs then
			local tooltipLines = {};
			local n = 1;
			tooltipLines[n] = L["Paragon Reward Available"];
			for _, factionID in ipairs(factionIDs) do
				n = n + 1;
				tooltipLines[n] = "- "..(FactionUtil:GetFactionName(factionID) or "");
			end
			return tooltipLines
		end
	else
		return FactionUtil:IsAnyParagonRewardPending(viewedExpansionOnly)
	end
end

local function FactionTab_OnSelected()
	if FactionTab then
		FactionTab:DisplayOverview();
	end
end

LandingPageUtil.AddTab(
	{
		key = "faction",
		name = L["Factions"],
		uiOrder = 1,
		initFunc = CreateFactionTab,
		notificationGetter = NotificationCheck,
		useCustomLeftFrame = true,
		onTabSelected = FactionTab_OnSelected,
	}
);

addon.CallbackRegistry:Register("LandingPage.SetFactionLayout", function(factionLayout)
	if not factionLayout then return end;

	FactionUtil.ActiveFactionLayout = factionLayout;

	if FactionTab then
		if FactionTab:IsShown() then
			FactionTab:OnLayoutChanged();
			FactionTab:RequestFullUpdate(true);
		else
			FactionTab.isLayoutDirty = true;
		end
	end
end);
