Quantcast
local addonName, L = ...

local objects = {}
local temporary = {}

local defaults = {
	toggle = true,
	items = true,
	faireport = true,
	gossip = true,
	gossipraid = 1,
	modifier = 'SHIFT',
	reverse = false,
	itemBlacklist = {
		-- Inscription weapons
		[31690] = 79343, -- Inscribed Tiger Staff
		[31691] = 79340, -- Inscribed Crane Staff
		[31692] = 79341, -- Inscribed Serpent Staff

		-- Darkmoon Faire artifacts
		[29443] = 71635, -- Imbued Crystal
		[29444] = 71636, -- Monstrous Egg
		[29445] = 71637, -- Mysterious Grimoire
		[29446] = 71638, -- Ornate Weapon
		[29451] = 71715, -- A Treatise on Strategy
		[29456] = 71951, -- Banner of the Fallen
		[29457] = 71952, -- Captured Insignia
		[29458] = 71953, -- Fallen Adventurer's Journal
		[29464] = 71716, -- Soothsayer's Runes

		-- Tiller Gifts
		['progress_79264'] = 79264, -- Ruby Shard
		['progress_79265'] = 79265, -- Blue Feather
		['progress_79266'] = 79266, -- Jade Cat
		['progress_79267'] = 79267, -- Lovely Apple
		['progress_79268'] = 79268, -- Marsh Lily

		-- Misc
		[31664] = 88604, -- Nat's Fishing Journal
	}
}

local Panel = CreateFrame('Frame', nil, InterfaceOptionsFramePanelContainer)
Panel.name = addonName
Panel:Hide()

Panel:RegisterEvent('PLAYER_LOGIN')
Panel:SetScript('OnEvent', function()
	local oldName = 'Monomyth'
	if(IsAddOnLoaded(oldName)) then
		DisableAddOn(oldName)
		print('|cffff8080QuickQuest:|r', string.format(L['You\'re running a conflicting addon (%s), type /reload to resolve'], oldName))
	end

	QuickQuestDB = QuickQuestDB or defaults

	-- TEMP: import from old DB
	if(QuickQuestDB.ignoredQuests) then
		QuickQuestDB.itemBlacklist = QuickQuestDB.ignoredQuests
		QuickQuestDB.ignoredQuests = nil
	end

	if(type(QuickQuestDB.gossipraid) == 'boolean') then
		if(QuickQuestDB.gossipraid) then
			QuickQuestDB.gossipraid = 0
		else
			QuickQuestDB.gossipraid = 2
		end
	end

	for key, value in next, defaults do
		if(QuickQuestDB[key] == nil) then
			QuickQuestDB[key] = value
		end
	end
end)

function Panel:okay()
	for key, value in next, temporary do
		QuickQuestDB[key] = value
	end

	table.wipe(temporary)
end

function Panel:cancel()
	table.wipe(temporary)
end

function Panel:default()
	for key, value in next, defaults do
		if(key ~= 'itemBlacklist') then
			QuickQuestDB[key] = value
		end
	end

	table.wipe(temporary)
end

function Panel:refresh()
	for key, object in next, objects do
		if(object:IsObjectType('CheckButton')) then
			object:SetChecked(QuickQuestDB[key])
		elseif(object:IsObjectType('Frame')) then
			object.Label:SetText(object.keys[QuickQuestDB[key]])
		end
	end
end

local function ToggleAll(self)
	local enabled = self:GetChecked()

	for _, object in next, objects do
		if(object:IsObjectType('CheckButton')) then
			if(enabled) then
				local parent = object.realParent
				if(not parent or parent:GetChecked()) then
					object:Enable()
					object.Text:SetTextColor(1, 1, 1)
				end
			else
				if(object ~= self) then
					object:Disable()
				end

				object.Text:SetTextColor(1/3, 1/3, 1/3)
			end
		elseif(object:IsObjectType('Frame')) then
			if(enabled) then
				object.Button:Enable()
				object.Label:SetTextColor(1, 1, 1)
				object.Text:SetTextColor(1, 1, 1)
			else
				object.Button:Disable()
				object.Label:SetTextColor(1/3, 1/3, 1/3)
				object.Text:SetTextColor(1/3, 1/3, 1/3)
			end
		end
	end
end

local CreateCheckButton
do
	local function ClickCheckButton(self)
		if(self:GetChecked()) then
			temporary[self.key] = true
		else
			temporary[self.key] = false
		end
	end

	function CreateCheckButton(parent, key, realParent)
		local CheckButton = CreateFrame('CheckButton', nil, parent, 'InterfaceOptionsCheckButtonTemplate')
		CheckButton:SetHitRectInsets(0, 0, 0, 0)
		CheckButton:SetScript('OnClick', ClickCheckButton)
		CheckButton.realParent = realParent
		CheckButton.key = key

		objects[key] = CheckButton

		return CheckButton
	end
end

local CreateDropdown
do
	local BACKDROP = {
		bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
		edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], edgeSize = 32,
		insets = {top = 12, bottom = 9, left = 11, right = 12}
	}

	local function OnHide(self)
		self.Menu:Hide()
	end

	local function MenuClick(self)
		local Menu = self:GetParent().Menu
		if(Menu:IsShown()) then
			Menu:Hide()
		else
			for key, Item in next, Menu.items do
				Item.Button:SetChecked(key == (temporary[Menu.key] or QuickQuestDB[Menu.key]))
			end

			Menu:Show()
		end

		PlaySound('igMainMenuOptionCheckBoxOn')
	end

	local function ItemClick(self)
		local Menu = self:GetParent()
		temporary[Menu.key] = self.value

		Menu:Hide()
		Menu:GetParent().Label:SetText(self:GetText())
	end

	local function Enable(self)
		self.Label:SetTextColor(1, 1, 1)
		self.Button:Enable()
	end

	local function Disable(self)
		self.Label:SetTextColor(1/3, 1/3, 1/3)
		self.Button:Disable()
	end

	function CreateDropdown(parent, key, items)
		local Dropdown = CreateFrame('Frame', nil, parent)
		Dropdown:SetSize(110, 32)
		Dropdown:SetScript('OnHide', OnHide)
		Dropdown.Enable = Enable
		Dropdown.Disable = Disable
		Dropdown.keys = items

		local LeftTexture = Dropdown:CreateTexture()
		LeftTexture:SetPoint('TOPLEFT', -14, 17)
		LeftTexture:SetSize(25, 64)
		LeftTexture:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
		LeftTexture:SetTexCoord(0, 0.1953125, 0, 1)

		local RightTexture = Dropdown:CreateTexture()
		RightTexture:SetPoint('TOPRIGHT', 14, 17)
		RightTexture:SetSize(25, 64)
		RightTexture:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
		RightTexture:SetTexCoord(0.8046875, 1, 0, 1)

		local MiddleTexture = Dropdown:CreateTexture()
		MiddleTexture:SetPoint('TOPLEFT', LeftTexture, 'TOPRIGHT')
		MiddleTexture:SetPoint('TOPRIGHT', RightTexture, 'TOPLEFT')
		MiddleTexture:SetTexture([[Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame]])
		MiddleTexture:SetTexCoord(0.1953125, 0.8046875, 0, 1)

		local Button = CreateFrame('Button', nil, Dropdown)
		Button:SetPoint('TOPRIGHT', RightTexture, -16, -18)
		Button:SetSize(24, 24)
		Button:SetNormalTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Up]])
		Button:SetPushedTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Down]])
		Button:SetDisabledTexture([[Interface\ChatFrame\UI-ChatIcon-ScrollDown-Disabled]])
		Button:SetHighlightTexture([[Interface\Buttons\UI-Common-MouseHilight]])
		Button:GetHighlightTexture():SetBlendMode('ADD')
		Button:SetScript('OnClick', MenuClick)
		Dropdown.Button = Button

		local Label = Dropdown:CreateFontString(nil, nil, 'GameFontHighlightSmall')
		Label:SetPoint('RIGHT', Button, 'LEFT')
		Label:SetSize(0, 10)
		Dropdown.Label = Label

		local Menu = CreateFrame('Frame', nil, Dropdown)
		Menu:SetPoint('TOPLEFT', Dropdown, 'BOTTOMLEFT', 0, 4)
		Menu:SetBackdrop(BACKDROP)
		Menu:SetFrameStrata('DIALOG')
		Menu:Hide()
		Menu.key = key
		Menu.items = {}
		Dropdown.Menu = Menu

		local index, maxWidth = 0, 0
		for value, name in next, items do
			local Item = CreateFrame('Button', nil, Menu)
			Item:SetPoint('TOPLEFT', 14, -(14 + (18 * index)))
			Item:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]])
			Item:GetHighlightTexture():SetBlendMode('ADD')
			Item:SetScript('OnClick', ItemClick)
			Item.value = value

			local ItemButton = CreateFrame('CheckButton', nil, Item)
			ItemButton:SetPoint('LEFT')
			ItemButton:SetSize(16, 16)
			ItemButton:SetNormalTexture([[Interface\Common\UI-DropDownRadioChecks]])
			ItemButton:GetNormalTexture():SetTexCoord(0.5, 1, 0.5, 1)
			ItemButton:SetCheckedTexture([[Interface\Common\UI-DropDownRadioChecks]])
			ItemButton:GetCheckedTexture():SetTexCoord(0, 0.5, 0.5, 1)
			ItemButton:EnableMouse(false)
			Item.Button = ItemButton

			local ItemLabel = Item:CreateFontString(nil, nil, 'GameFontHighlightSmall')
			ItemLabel:SetPoint('LEFT', ItemButton, 'RIGHT', 4, -1)
			ItemLabel:SetText(name)
			Item:SetFontString(ItemLabel)

			local width = ItemLabel:GetWidth()
			if(width > maxWidth) then
				maxWidth = width
			end

			Menu.items[value] = Item
			index = index + 1
		end

		for _, Item in next, Menu.items do
			Item:SetSize(32 + maxWidth, 18)
		end

		Menu:SetSize(60 + maxWidth, 28 + 18 * index)

		local Text = Dropdown:CreateFontString(nil, nil, 'GameFontHighlight')
		Text:SetPoint('LEFT', Dropdown, 'RIGHT', 3, 2)
		Dropdown.Text = Text

		objects[key] = Dropdown

		return Dropdown
	end
end

Panel:SetScript('OnShow', function(self)
	local Title = self:CreateFontString(nil, nil, 'GameFontNormalLarge')
	Title:SetPoint('TOPLEFT', 16, -16)
	Title:SetText(addonName)

	local Description = self:CreateFontString(nil, nil, 'GameFontHighlightSmall')
	Description:SetPoint('TOPLEFT', Title, 'BOTTOMLEFT', 0, -8)
	Description:SetPoint('RIGHT', -32, 0)
	Description:SetJustifyH('LEFT')
	Description:SetText(L['Less clicking, more action!'])
	self.Description = Description

	local Toggle = CreateCheckButton(self, 'toggle')
	Toggle:SetPoint('TOPLEFT', Description, 'BOTTOMLEFT', -2, -10)
	Toggle:HookScript('OnClick', ToggleAll)
	Toggle.Text:SetText(L['Enable automating'])

	local Items = CreateCheckButton(self, 'items')
	Items:SetPoint('TOPLEFT', Toggle, 'BOTTOMLEFT', 0, -8)
	Items.Text:SetText(L['Start quests from items'])

	local Gossip = CreateCheckButton(self, 'gossip')
	Gossip:SetPoint('TOPLEFT', Items, 'BOTTOMLEFT', 0, -8)
	Gossip.Text:SetText(L['Select gossip option if there is only one'])

	local GossipRaid = CreateDropdown(self, 'gossipraid', {
		[0] = L['Never'],
		[1] = L['Soloing'],
		[2] = L['Always']
	})
	GossipRaid:SetPoint('TOPLEFT', Gossip, 'BOTTOMLEFT', 24, -10)
	GossipRaid.Text:SetText(L['When to select gossip while in a raid'])

	Gossip:HookScript('OnClick', function(self)
		if(self:GetChecked()) then
			GossipRaid:Enable()
			GossipRaid.Text:SetTextColor(1, 1, 1)
		else
			GossipRaid:Disable()
			GossipRaid.Text:SetTextColor(1/3, 1/3, 1/3)
		end
	end)

	if(QuickQuestDB.gossip) then
		GossipRaid:Enable()
		GossipRaid.Text:SetTextColor(1, 1, 1)
	else
		GossipRaid:Disable()
		GossipRaid.Text:SetTextColor(1/3, 1/3, 1/3)
	end

	local Darkmoon = CreateCheckButton(self, 'faireport')
	Darkmoon:SetPoint('TOPLEFT', GossipRaid, 'BOTTOMLEFT', -24, -8)
	Darkmoon.Text:SetText(L['Darkmoon Faire: Automatically teleport'])

	local Modifier = CreateDropdown(self, 'modifier', {
		ALT = L['ALT key'],
		CTRL = L['CTRL key'],
		SHIFT = L['SHIFT key']
	})
	Modifier:SetPoint('TOPLEFT', Darkmoon, 'BOTTOMLEFT', 0, -14)

	if(QuickQuestDB.reverse) then
		Modifier.Text:SetText(L['Modifier to temporarly enable automation'])
	else
		Modifier.Text:SetText(L['Modifier to temporarly disable automation'])
	end

	local Reverse = CreateCheckButton(self, 'reverse')
	Reverse:SetPoint('TOPLEFT', Modifier, 'BOTTOMLEFT', 24, -8)
	Reverse.Text:SetText(L['Reverse the behaviour of the modifier key'])
	Reverse:HookScript('OnClick', function(self)
		if(self:GetChecked()) then
			Modifier.Text:SetText(L['Modifier to temporarly enable automation'])
		else
			Modifier.Text:SetText(L['Modifier to temporarly disable automation'])
		end
	end)

	Panel:refresh()
	ToggleAll(Toggle)

	self:SetScript('OnShow', nil)
end)

local containerBackdrop = {
	bgFile = [[Interface\ChatFrame\ChatFrameBackground]], tile = true, tileSize = 16,
	edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
	insets = {left = 4, right = 4, top = 4, bottom = 4}
}

local ItemPanel = CreateFrame('Frame', nil, Panel)
ItemPanel.name = 'Item Blacklist'
ItemPanel.parent = addonName
ItemPanel:Hide()

function ItemPanel:default()
	table.wipe(QuickQuestDB.itemBlacklist)

	for quest, item in next, defaults.itemBlacklist do
		QuickQuestDB.itemBlacklist[quest] = item
	end

	self:UpdateList()
end

local items = {}

StaticPopupDialogs.QUICKQUEST_ITEM_REMOVE = {
	text = L['Are you sure you want to delete\n|T%s:16|t%s\nfrom the filter?'],
	button1 = 'Yes',
	button2 = 'No',
	OnAccept = function(self, data)
		QuickQuestDB.itemBlacklist[data.questID] = nil
		items[data.itemID] = nil
		data.button:Hide()

		ItemPanel:UpdateList()
	end,
	timeout = 0,
	hideOnEscape = true,
	preferredIndex = 3, -- Avoid some taint
}

ItemPanel:SetScript('OnShow', function(self)
	local Title = self:CreateFontString(nil, nil, 'GameFontHighlight')
	Title:SetPoint('TOPLEFT', 20, -20)
	Title:SetText(L['Items filtered from automation'])

	local Description = CreateFrame('Button', nil, self)
	Description:SetPoint('LEFT', Title, 'RIGHT')
	Description:SetNormalTexture([[Interface\GossipFrame\ActiveQuestIcon]])
	Description:SetSize(16, 16)

	Description:SetScript('OnLeave', GameTooltip_Hide)
	Description:SetScript('OnEnter', function(self)
		GameTooltip:SetOwner(self, 'ANCHOR_TOPLEFT')
		GameTooltip:AddLine(L.ItemBlacklistTooltip, 1, 1, 1)
		GameTooltip:Show()
	end)

	local Items = CreateFrame('Frame', nil, self)
	Items:SetPoint('TOPLEFT', Title, 'BOTTOMLEFT', -12, -8)
	Items:SetPoint('BOTTOMRIGHT', -8, 8)
	Items:SetBackdrop(containerBackdrop)
	Items:SetBackdropColor(0, 0, 0, 1/2)

	local Boundaries = CreateFrame('Frame', nil, Items)
	Boundaries:SetPoint('TOPLEFT', 8, -8)
	Boundaries:SetPoint('BOTTOMRIGHT', -8, 8)

	local function ItemOnClick(self, button)
		if(button == 'RightButton') then
			local _, link, _, _, _, _, _, _, _, texture = GetItemInfo(self.itemID)
			local dialog = StaticPopup_Show('QUICKQUEST_ITEM_REMOVE', texture, link)
			dialog.data = {
				itemID = self.itemID,
				questID = self.questID,
				button = self
			}
		end
	end

	local function ItemOnEnter(self)
		GameTooltip:SetOwner(self, 'ANCHOR_TOPLEFT')
		GameTooltip:SetItemByID(self.itemID)
		GameTooltip:AddLine(' ')
		GameTooltip:AddLine(L['Right-click to remove from list'], 0, 1, 0)
		GameTooltip:Show()
	end

	self.UpdateList = function()
		local index = 1
		local width = Boundaries:GetWidth()
		local cols = math.floor((width > 0 and width or 591) / 36)

		for quest, item in next, QuickQuestDB.itemBlacklist do
			local Button = items[item]
			if(not Button) then
				Button = CreateFrame('Button', nil, Items)
				Button:SetSize(34, 34)
				Button:RegisterForClicks('AnyUp')

				local Texture = Button:CreateTexture()
				Texture:SetAllPoints()
				Button.Texture = Texture

				Button:SetScript('OnClick', ItemOnClick)
				Button:SetScript('OnEnter', ItemOnEnter)
				Button:SetScript('OnLeave', GameTooltip_Hide)

				items[item] = Button
			end

			local _, _, _, _, _, _, _, _, _, textureFile = GetItemInfo(item)

			if(textureFile) then
				Button.Texture:SetTexture(textureFile)
			elseif(not queryItems) then
				self:RegisterEvent('GET_ITEM_INFO_RECEIVED')
				queryItems = true
			end

			Button:ClearAllPoints()
			Button:SetPoint('TOPLEFT', Boundaries, (index - 1) % cols * 36, math.floor((index - 1) / cols) * -36)

			Button.questID = quest
			Button.itemID = item

			index = index + 1
		end

		if(not queryItems) then
			self:UnregisterEvent('GET_ITEM_INFO_RECEIVED')
		end
	end

	self:UpdateList()

	Items:SetScript('OnMouseUp', function()
		if(CursorHasItem()) then
			local _, itemID, link = GetCursorInfo()

			for bag = 0, 4 do
				for slot = 1, GetContainerNumSlots(bag) do
					if(GetContainerItemLink(bag, slot) == link) then
						local _, questID = GetContainerItemQuestInfo(bag, slot)
						if(not questID) then
							questID = string.format('progress_%s', itemID)
						end

						if(not QuickQuestDB.itemBlacklist[questID]) then
							QuickQuestDB.itemBlacklist[questID] = itemID
							ClearCursor()

							self:UpdateList()
							return
						end
					end
				end
			end
		end
	end)

	self:SetScript('OnShow', nil)
end)

ItemPanel:HookScript('OnEvent', function(self, event)
	if(event == 'GET_ITEM_INFO_RECEIVED') then
		self:UpdateList()
	end
end)

InterfaceOptions_AddCategory(Panel)
InterfaceOptions_AddCategory(ItemPanel)

SLASH_QuickQuest1 = '/qq'
SLASH_QuickQuest2 = '/quickquest'
SlashCmdList[addonName] = function()
	-- On first load IOF doesn't select the right category or panel, this is a dirty fix
	InterfaceOptionsFrame_OpenToCategory(addonName)
	InterfaceOptionsFrame_OpenToCategory(addonName)
end