--[[
PopupPower
previously StaticPopupMultiLineEditBox

By: Karl (AnduinLothar) Isenberg <karlkfi@cosmosui.org>

Allows you to have multi-line editboxes with the default Static Popup config. 

$Id: PopupPower.lua 3078 2006-02-17 00:05:43Z karlkfi $
$Rev: 3078 $
$LastChangedBy: karlkfi $
$Date: 2006-02-16 18:05:43 -0600 (Thu, 16 Feb 2006) $

Change List:
v1.1
- Prepared for Lua 5.1
v1.0
- Initial Release

--]]

PopupPower = {};

PopupPower.PlugIns = {};

function PopupPower.OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
end

function PopupPower.OnEvent(event)
	if (event == "VARIABLES_LOADED") then
		PopupPower.Setup()
	end
end

--POPUPPOWER_ID_FROM_LINK = "|Hitem:((.-):(.-):(.-):(.-))|h%[(.-)%]|h";
--local fullItemID itemID, permEnchant, tempEnchant, suffix, itemName = string.gfind(GetLootSlotLink(LootFrame.selectedSlot), POPUPPOWER_ID_FROM_LINK)();


--------------------------------------------------
-- Function Hooks (StaticPopup.lua functions)
--------------------------------------------------

function PopupPower.StaticPopup_Show_Hook(which, text_arg1, text_arg2, data)
	local info = StaticPopupDialogs[which];
	if ( not info ) then
		return nil;
	end
	--local data = arg1;
	--Sea.io.printComma("StaticPopup_Show: ", which, text_arg1, text_arg2, data, arg1, arg2);
	if ( UnitIsDeadOrGhost("player") and not info.whileDead ) then
		if ( info.OnCancel ) then
			info.OnCancel();
		end
		return nil;
	end

	if ( InCinematic() and not info.interruptCinematic ) then
		if ( info.OnCancel ) then
			info.OnCancel();
		end
		return nil;
	end

	if ( info.exclusive ) then
		for index = 1, STATICPOPUP_NUMDIALOGS do
			local frame = getglobal("StaticPopup"..index);
			if ( frame:IsShown() and StaticPopupDialogs[frame.which].exclusive ) then
				--Sea.io.printComma("StaticPopup_Show: exclusive closed:", frame.which, " by ", which, frame.data);
				frame:Hide();
				local OnCancel = StaticPopupDialogs[frame.which].OnCancel;
				if ( OnCancel ) then
					OnCancel(frame.data, "override");
				end
				break;
			end
		end
	end
	
	if ( info.cancels == "ALL" ) then
		for index = 1, STATICPOPUP_NUMDIALOGS do
			local frame = getglobal("StaticPopup"..index);
			local frameInfo = StaticPopupDialogs[frame.which];
			if ( frame:IsShown() and frameInfo ) then
				-- notCanceledBy
				if ( not frameInfo.notCanceledBy or not frameInfo.notCanceledBy[which] ) then
					--Sea.io.printComma("StaticPopup_Show: cancel ALL closed:", frame.which, " by ", which, frame.data);
					frame:Hide();
					local OnCancel = frameInfo.OnCancel;
					if ( OnCancel ) then
						OnCancel(frame.data, "override");
					end
				end
			end
		end
	elseif ( info.cancels ) then
		for index = 1, STATICPOPUP_NUMDIALOGS do
			local frame = getglobal("StaticPopup"..index);
			if ( frame:IsShown() and (frame.which == info.cancels) ) then
				--Sea.io.printComma("StaticPopup_Show: cancel closed:", frame.which, " by ", which, frame.data);
				frame:Hide();
				local OnCancel = StaticPopupDialogs[frame.which].OnCancel;
				if ( OnCancel ) then
					OnCancel(frame.data, "override");
				end
			end
		end
	end

	-- Pick a free dialog to use
	local dialog = nil;
	-- Find an open dialog of the requested type
	dialog = StaticPopup_FindVisible(which, data);
	if ( dialog ) then
		--Sea.io.printComma("StaticPopup_Show: FindVisible closed:", which, frame.data);
		local OnCancel = StaticPopupDialogs[which].OnCancel;
		if ( OnCancel ) then
			OnCancel(dialog.data, "override");
		end
		dialog:Hide();
	else
		-- Find a free dialog
		for index = 1, STATICPOPUP_NUMDIALOGS do
			local frame = getglobal("StaticPopup"..index);
			if ( not frame:IsShown() ) then
				dialog = frame;
				break;
			end
		end
		if ( not dialog ) then
			--Sea.io.printComma("StaticPopup_Show: all taken closed:", which, frame.data);
			info.OnCancel();
			return nil;
		end
	end

	-- Set the text of the dialog
	local text = getglobal(dialog:GetName().."Text");
	if ( type(info.text) == "function" ) then
		text:SetText(info.text(text_arg1, text_arg2));
	elseif (text_arg2) then
		text:SetText(format(info.text, text_arg1, text_arg2));
	elseif (text_arg1) then
		text:SetText(format(info.text, text_arg1));
	else
		text:SetText(info.text);
	end
	text.text_arg1 = text_arg1;
	text.text_arg2 = text_arg2;
	
	
	local multiLineEditBox = getglobal(dialog:GetName().."MultiLineScrollFrameEditBox");
	local multiLineEditBoxContainer = multiLineEditBox:GetParent();
	local wideEditBox = getglobal(dialog:GetName().."WideEditBox");
	local editBox = getglobal(dialog:GetName().."EditBox");
	local alertIcon = getglobal(dialog:GetName().."AlertIcon");
	alertIcon:Hide();
	dialog:SetWidth(320);
	if ( info.extraWide ) then
		-- Widen
		dialog:SetWidth(420);
	elseif ( info.showAlert ) then
		-- If is the delete item dialog display the error image
		dialog:SetWidth(420);
		alertIcon:Show();
	end
	
	-- Item Button
	local itemIcon = getglobal(dialog:GetName().."ItemIcon");
	itemIcon:Hide();
	itemIcon.setTooltip = nil;
	if ( info.itemTexture ) then
		-- Show the item texture
		local itemIconTexture = getglobal(dialog:GetName().."ItemIconTexture");
		if ( type(info.itemTexture) == "function" ) then
			local texture = info.itemTexture();
			if ( texture ) then
				itemIconTexture:SetTexture(texture)
				itemIcon:Show();
			end
		else
			local texture = info.itemTexture;
			itemIconTexture:SetTexture(texture);
			itemIcon:Show();
		end
		
		-- Update the tooltip setting function
		itemIcon.setTooltip = info.setItemTooltip;
	end

	-- If is the ticket edit dialog then show the close button
	if ( info.hasCloseButton ) then
		getglobal(dialog:GetName().."CloseButton"):Show();
		dialog:SetWidth(dialog:GetWidth()+30);
	else
		getglobal(dialog:GetName().."CloseButton"):Hide();
	end

	-- Set the editbox of the dialog
	if ( StaticPopupDialogs[which].hasEditBox ) then
		if ( StaticPopupDialogs[which].hasMultiLineEditBox ) then
			multiLineEditBoxContainer:Show();
			wideEditBox:Hide();
			editBox:Hide();

			if ( StaticPopupDialogs[which].maxLetters ) then
				multiLineEditBox:SetMaxLetters(StaticPopupDialogs[which].maxLetters);
			end
			if ( StaticPopupDialogs[which].maxBytes ) then
				multiLineEditBox:SetMaxBytes(StaticPopupDialogs[which].maxBytes);
			end
		elseif ( StaticPopupDialogs[which].hasWideEditBox ) then
			multiLineEditBoxContainer:Hide();
			wideEditBox:Show();
			editBox:Hide();

			if ( StaticPopupDialogs[which].maxLetters ) then
				wideEditBox:SetMaxLetters(StaticPopupDialogs[which].maxLetters);
			end
			if ( StaticPopupDialogs[which].maxBytes ) then
				wideEditBox:SetMaxBytes(StaticPopupDialogs[which].maxBytes);
			end
		else
			multiLineEditBoxContainer:Hide();
			wideEditBox:Hide();
			editBox:Show();

			if ( StaticPopupDialogs[which].maxLetters ) then
				editBox:SetMaxLetters(StaticPopupDialogs[which].maxLetters);
			end
			if ( StaticPopupDialogs[which].maxBytes ) then
				editBox:SetMaxBytes(StaticPopupDialogs[which].maxBytes);
			end
		end
	else
		multiLineEditBoxContainer:Hide();
		wideEditBox:Hide();
		editBox:Hide();
	end
	multiLineEditBox:SetText("");
	wideEditBox:SetText("");
	editBox:SetText("");
	
	-- Show or hide money frame
	if ( StaticPopupDialogs[which].hasMoneyFrame ) then
		getglobal(dialog:GetName().."MoneyFrame"):Show();	
	else
		getglobal(dialog:GetName().."MoneyFrame"):Hide();
	end

	-- Set the buttons of the dialog
	local button1 = getglobal(dialog:GetName().."Button1");
	local button2 = getglobal(dialog:GetName().."Button2");
	if ( StaticPopupDialogs[which].button2 and
	   ( not StaticPopupDialogs[which].DisplayButton2 or StaticPopupDialogs[which].DisplayButton2() ) ) then
		button1:ClearAllPoints();
		button2:ClearAllPoints();
		if ( StaticPopupDialogs[which]. hasMultiLineEditBox ) then
			button1:SetPoint("TOPRIGHT", dialog:GetName().."MultiLineScrollFrameBackground", "BOTTOM", -6, -8);
			button2:SetPoint("LEFT", button1, "RIGHT", 13, 0);
		elseif ( StaticPopupDialogs[which].hasEditBox ) then
			button1:SetPoint("TOPRIGHT", editBox, "BOTTOM", -6, -8);
			button2:SetPoint("LEFT", button1, "RIGHT", 13, 0);
		elseif ( StaticPopupDialogs[which].hasMoneyFrame ) then
			button1:SetPoint("TOPRIGHT", text, "BOTTOM", -6, -24);
			button2:SetPoint("LEFT", button1, "RIGHT", 13, 0);
		else
			button1:SetPoint("TOPRIGHT", text, "BOTTOM", -6, -8);
			button2:SetPoint("LEFT", button1, "RIGHT", 13, 0);
		end
		button2:SetText(StaticPopupDialogs[which].button2);
		local width = button2:GetTextWidth();
		if ( width > 110 ) then
			button2:SetWidth(width + 20);
		else
			button2:SetWidth(120);
		end
		button2:Show();
	else
		button1:ClearAllPoints();
		button1:SetPoint("TOP", text, "BOTTOM", 0, -8);
		button2:Hide();
	end
	if ( StaticPopupDialogs[which].button1 ) then
		button1:SetText(StaticPopupDialogs[which].button1);
		local width = button1:GetTextWidth();
		if ( width > 120 ) then
			button1:SetWidth(width + 20);
		else
			button1:SetWidth(120);
		end
		button1:Show();
	else
		button1:Hide();
	end

	-- Set the miscellaneous variables for the dialog
	dialog.which = which;
	dialog.timeleft = StaticPopupDialogs[which].timeout;
	dialog.hideOnEscape = StaticPopupDialogs[which].hideOnEscape;
	-- Clear out data
	dialog.data = nil;

	if ( StaticPopupDialogs[which].StartDelay ) then
		dialog.startDelay = StaticPopupDialogs[which].StartDelay();
		button1:Disable();
	else
		dialog.startDelay = nil;
		button1:Enable();
	end

	-- Finally size and show the dialog
	StaticPopup_Resize(dialog, which);
	dialog:Show();

	if ( StaticPopupDialogs[which].sound ) then
		PlaySound(StaticPopupDialogs[which].sound);
	end
	--Sea.io.printComma("StaticPopup_Show: returning:", which, " as ", dialog:GetName(), data, dialog.data);
	return dialog;
end

function PopupPower.StaticPopup_EditBoxOnEnterPressed_Hook()
	local parent;
	if (this.withinScrollFrame) then
		parent = this:GetParent():GetParent();
	else
		parent = this:GetParent();
	end
	EditBoxOnEnterPressed = StaticPopupDialogs[parent.which].EditBoxOnEnterPressed;
	if ( EditBoxOnEnterPressed ) then
		EditBoxOnEnterPressed(parent.data, parent.data2);
		parent:Hide();
	end
end

function PopupPower.StaticPopup_EditBoxOnEscapePressed_Hook()
	this:ClearFocus();
	local parent;
	if (this.withinScrollFrame) then
		parent = this:GetParent():GetParent();
	else
		parent = this:GetParent();
	end
	local EditBoxOnEscapePressed = StaticPopupDialogs[parent.which].EditBoxOnEscapePressed;
	if ( EditBoxOnEscapePressed ) then
		EditBoxOnEscapePressed(parent.data, parent.data2);
	end
end

function PopupPower.StaticPopup_Resize_Hook(dialog, which)
	local text = getglobal(dialog:GetName().."Text");
	local button1 = getglobal(dialog:GetName().."Button1");
	if ( StaticPopupDialogs[which].hasEditBox ) then
		if ( StaticPopupDialogs[which].hasMultiLineEditBox ) then
			dialog:SetHeight(16 + text:GetHeight() + 8 + getglobal(dialog:GetName().."MultiLineScrollFrameBackground"):GetHeight() + 8 + button1:GetHeight() + 36);
		else
			dialog:SetHeight(16 + text:GetHeight() + 8 + getglobal(dialog:GetName().."EditBox"):GetHeight() + 8 + button1:GetHeight() + 16);
		end
	elseif ( StaticPopupDialogs[which].hasMoneyFrame ) then
		dialog:SetHeight(16 + text:GetHeight() + 8 + button1:GetHeight() + 32);
	else
		dialog:SetHeight(16 + text:GetHeight() + 8 + button1:GetHeight() + 16);
	end
end

--------------------------------------------------
-- Extra StaticPopup Functions
--------------------------------------------------

function StaticPopup_EditBoxOnTextChanged()
	this.textChanged = 1;
	local parent;
	if (this.withinScrollFrame) then
		parent = this:GetParent():GetParent();	
	
		local scrollBar = getglobal(this:GetParent():GetName().."ScrollBar")
		this:GetParent():UpdateScrollChildRect();
		local min;
		local max;
		min, max = scrollBar:GetMinMaxValues();
		if ( max > 0 and (this.max ~= max) ) then
			this.max = max;
			scrollBar:SetValue(max);
		end
	else
		parent = this:GetParent();
	end
	
	parent.data2 = this:GetText();
	
	local EditBoxOnTextChanged = StaticPopupDialogs[parent.which].EditBoxOnTextChanged;
	if ( EditBoxOnTextChanged ) then
		EditBoxOnTextChanged(parent.data, parent.data2);
	end
end

function StaticPopup_EditBox_GetStaticPopupFrame()
	if (this.withinScrollFrame) then
		return this:GetParent():GetParent();
	else
		return this:GetParent();
	end
end

function StaticPopup_GetEditBox(which)
	if (which) then
		local frame = StaticPopup_FindVisible(which);
		if (frame) then
			if (StaticPopupDialogs[which].hasMultiLineEditBox) then
				return getglobal(frame:GetName().."MultiLineScrollFrameEditBox");
			else
				return getglobal(frame:GetName().."EditBox");
			end
		end
	else
		if (StaticPopupDialogs[this:GetParent().which].hasMultiLineEditBox) then
			return getglobal(this:GetParent():GetName().."MultiLineScrollFrameEditBox");
		else
			return getglobal(this:GetParent():GetName().."EditBox");
		end
	end
end

--------------------------------------------------
-- Setup
--------------------------------------------------

function PopupPower.Setup()	
	
	-- Manual Replace Hooks (will break any previous hooks)
	PopupPower.StaticPopup_Show_Orig = StaticPopup_Show;
	StaticPopup_Show = PopupPower.StaticPopup_Show_Hook;
	
	PopupPower.StaticPopup_EditBoxOnEnterPressed_Orig = StaticPopup_EditBoxOnEnterPressed;
	StaticPopup_EditBoxOnEnterPressed = PopupPower.StaticPopup_EditBoxOnEnterPressed_Hook;
	
	PopupPower.StaticPopup_EditBoxOnEscapePressed_Orig = StaticPopup_EditBoxOnEscapePressed;
	StaticPopup_EditBoxOnEscapePressed = PopupPower.StaticPopup_EditBoxOnEscapePressed_Hook;
	
	PopupPower.StaticPopup_Resize_Hook_Orig = StaticPopup_Resize;
	StaticPopup_Resize = PopupPower.StaticPopup_Resize_Hook;

	
	StaticPopup1EditBox:SetScript("OnTextChanged", StaticPopup_EditBoxOnTextChanged);
	StaticPopup2EditBox:SetScript("OnTextChanged", StaticPopup_EditBoxOnTextChanged);
	StaticPopup3EditBox:SetScript("OnTextChanged", StaticPopup_EditBoxOnTextChanged);
	StaticPopup4EditBox:SetScript("OnTextChanged", StaticPopup_EditBoxOnTextChanged);
	
	StaticPopupDialogs["DEATH"].extraWide = 1;
	StaticPopupDialogs["SET_GUILDMOTD"].extraWide = 1;
	StaticPopupDialogs["SET_GUILDPLAYERNOTE"].extraWide = 1;
	StaticPopupDialogs["SET_GUILDPLAYERNOTE"].extraWide = 1;
	StaticPopupDialogs["SET_GUILDOFFICERNOTE"].extraWide = 1;
	
	-- Update format to use info.notCanceledBy
	for which, info in pairs(StaticPopupDialogs) do
		
		if (info.notClosableByLogout) then
			if (not StaticPopupDialogs[which].notCanceledBy) then
				StaticPopupDialogs[which].notCanceledBy = {};
			end
			StaticPopupDialogs[which].notCanceledBy["CAMP"] = 1;
			StaticPopupDialogs[which].notCanceledBy["QUIT"] = 1;
		end
		
		if (info.whileDead) then
			if (not StaticPopupDialogs[which].notCanceledBy) then
				StaticPopupDialogs[which].notCanceledBy = {};
			end
			StaticPopupDialogs[which].notCanceledBy["DEATH"] = 1;
		end
		
	end
	
	StaticPopupDialogs["CAMP"].cancels = "ALL";
	StaticPopupDialogs["QUIT"].cancels = "ALL";
	StaticPopupDialogs["DEATH"].cancels = "ALL";
	
	-- info.text can be a function, passes the two arguments
	StaticPopupDialogs["BILLING_NAG"].text = function(text_arg1, text_arg2)
		format(BILLING_NAG_DIALOG, text_arg1, GetText("MINUTES", nil, text_arg1))
	end
	
	-- info.hasCloseButton shows top right close button
	StaticPopupDialogs["HELP_TICKET"].hasCloseButton = 1;
	
	for pluginName, info in pairs(PopupPower.PlugIns) do
		if (type(info.Setup) == "function") then
			info.Setup();
		end
	end
	
end
