local BtWQuestsDatabase = BtWQuestsDatabase
local BtWQuestsCharacters = BtWQuestsCharacters

local BTWQUESTS_CATEGORY_ITEM_WIDTH = 174
local BTWQUESTS_CATEGORY_ITEM_HEIGHT = 96
local BTWQUESTS_CATEGORY_ITEM_PADDING = 12
local BTWQUESTS_CATEGORY_NUM_ITEMS_PER_ROW = 4

local BTWQUESTS_CHAIN_ITEM_WIDTH = 174 / 2
local BTWQUESTS_CHAIN_ITEM_HEIGHT = 80

BtWQuestsFrameChainViewMixin = {}
function BtWQuestsFrameChainViewMixin:GetTooltip()
    return BtWQuestsFrame.Tooltip
end
function BtWQuestsFrameChainViewMixin:SelectFromLink(...)
    return BtWQuestsFrame:SelectFromLink(...)
end
function BtWQuestsFrameChainViewMixin:GetCharacter()
    return BtWQuestsFrame:GetCharacter()
end


BtWQuestSettingsData = {
    options = {
        {
            name = "Show minimap icon",
            value = "minimapShown",
            onChange = function (id, value)
                BtWQuestsMinimapButton:SetShown(value)
            end,
            default = true,
        },
        {
            name = "Show map pins",
            value = "showMapPins",
            default = false,
        },
        {
            name = "Show category as grid",
            value = "gridView",
            default = true,
        },
        {
            name = "Show category headers",
            value = "categoryHeaders",
            default = false,
        },
        {
            name = "Group completed",
            value = "filterCompleted",
            default = false,
        },
        {
            name = "Group ignored",
            value = "filterIgnored",
            default = false,
        },
    },
    optionsByID = {
    },
    GetValue = function (self, id)
        if BtWQuests_Settings == nil then
            BtWQuests_Settings = {}
        end
        
        local value = BtWQuests_Settings[id]
        if value == nil then
            value = self.optionsByID[id].default
        end
        return value
    end,
    SetValue = function (self, id, value)
        if BtWQuests_Settings == nil then
            BtWQuests_Settings = {}
        end
        BtWQuests_Settings[id] = value

        local func = self.optionsByID[id].onChange
        if func then
            func(id, value)
        end
    end
}
for _,option in ipairs(BtWQuestSettingsData.options) do
    BtWQuestSettingsData.optionsByID[option.value] = option
end

BtWQuestsOptionsMenuMixin = {}
function BtWQuestsOptionsMenuMixin:OnLoad()
	self.displayMode = "MENU"
end
function BtWQuestsOptionsMenuMixin:Initialize()
    local function Select (button)
        BtWQuestSettingsData:SetValue(button.value, not button.checked)
        if BtWQuestsFrame:IsShown() then
            BtWQuestsFrame:Refresh()
        end
    end

    local info = self:CreateInfo();
    info.isNotRadio = true
    -- info.keepShownOnClick = true

    for _,option in ipairs(BtWQuestSettingsData.options) do
        info.text = option.name
        info.value = option.value
        info.checked = BtWQuests_Settings[option.value]
        info.func = Select
        if info.checked == nil then
            info.checked = option.default
        end
        self:AddButton(info)
    end
end

BtWQuestsMixin = {}
function BtWQuestsMixin:GetCharacter()
    return self.Character or BtWQuestsCharacters:GetPlayer()
end
function BtWQuestsMixin:SelectCharacter(name, realm)
    local key
    if realm == nil then
        key = name
    else
        key = name .. "-" .. realm
    end

    local character = BtWQuestsCharacters:GetCharacter(key)
    if character ~= nil then
        self.Character = character
        UIDropDownMenu_SetText(self.CharacterDropDown, key)

        self:Refresh()
    end
end

function BtWQuestsMixin:GetExpansion()
    return self.expansionID
end
function BtWQuestsMixin:SetExpansion(id)
    self.expansionID = tonumber(id)
    self.categoryID = nil
    self.chainID = nil
end
function BtWQuestsMixin:SelectExpansion(id, scrollTo, noHistory)
    if not noHistory then
        self:UpdateCurrentHistory()
    end

    self:SetExpansion(id)
    
    if id == nil then
        self.navBar:Reset()
    else
        self.navBar:SetExpansion(id)
    end
    
    local expansion = self:GetExpansion()
    if expansion and BtWQuestsDatabase:HasExpansion(expansion) then
        self.ExpansionDropDown:SetText(BtWQuestsDatabase:GetExpansionByID(expansion));
    end

    if expansion == nil then
        self:DisplayExpansionList(scrollTo)
    else
        self:DisplayCurrentExpansion(scrollTo)
    end

    if not noHistory then
        self:AddCurrentToHistory()
    end
end

function BtWQuestsMixin:GetCategory()
    return self.categoryID
end
function BtWQuestsMixin:SetCategory(id)
    if id == nil then
        self.categoryID = nil
        self.chainID = nil
    else
        self.categoryID = tonumber(id)
        self.chainID = nil
        self.expansionID = select(4, BtWQuestsDatabase:GetCategoryByID(self.categoryID, self:GetCharacter()))
    end
end
function BtWQuestsMixin:SelectCategory(id, scrollTo, noHistory)
    if not noHistory then
        self:UpdateCurrentHistory()
    end
    
    self:SetCategory(id)
    
    self.navBar:SetCategory(id)
    
    local expansion = self:GetExpansion()
    if expansion and BtWQuestsDatabase:HasExpansion(expansion) then
        self.ExpansionDropDown:SetText(BtWQuestsDatabase:GetExpansionByID(expansion));
    end

    self:DisplayCurrentCategory(scrollTo)

    if not noHistory then
        self:AddCurrentToHistory()
    end
end

function BtWQuestsMixin:GetChain()
    return self.chainID
end
function BtWQuestsMixin:SetChain(id)
    self.chainID = tonumber(id)
    self.expansionID, self.categoryID = select(4, BtWQuestsDatabase:GetChainByID(self.chainID, self:GetCharacter()))
end
function BtWQuestsMixin:SelectChain(id, scrollTo, noHistory)
    if not noHistory then
        self:UpdateCurrentHistory()
    end
    
    self:SetChain(id)
    
    self.navBar:SetChain(id)
    
    local expansion = self:GetExpansion()
    if expansion and BtWQuestsDatabase:HasExpansion(expansion) then
        self.ExpansionDropDown:SetText(BtWQuestsDatabase:GetExpansionByID(expansion));
    end

    self:DisplayCurrentChain(scrollTo)
    
    if not noHistory then
        self:AddCurrentToHistory()
    end
end

function BtWQuestsMixin:SelectFromLink(link, scrollTo)
    local _, _, color, type, text, name = string.find(link, "|cff(%x*)|H([^:]+):([^|]+)|h%[([^%[%]]*)%]|h|r")
    if not color then
        _, _, type, text = string.find(link, "([^:]+):(.+)")
    end
    
    assert(type == "quest" or type == "btwquests")
    
    if type == "quest" then
        local _, _, id = string.find(text, "^(%d+):")

        id = tonumber(id)
        
        local questLogIndex = GetQuestLogIndexByID(id);
        if questLogIndex > 0 then
            if IsQuestComplete(id) and GetQuestLogIsAutoComplete(questLogIndex) then
                AutoQuestPopupTracker_RemovePopUp(id);
                ShowQuestComplete(questLogIndex);
                
                return true
            else
                QuestMapFrame_OpenToQuestDetails(id)
                
                return true
            end
        end
    elseif type == "btwquests" then
        local _, _, subtype, id = string.find(text, "^([^:]*):(%d+)")
        
        assert(subtype == "expansion" or subtype == "category" or subtype == "chain")
        
        if subtype == "expansion" then
            self:SelectExpansion(id, scrollTo)
            
            return true
        elseif subtype == "category" then
            self:SelectCategory(id, scrollTo)
            
            return true
        elseif subtype == "chain" then
            self:SelectChain(id, scrollTo)
            
            return true
        end
    end
    
    return false
end
function BtWQuestsMixin:SelectItem(item, scrollTo)
    if item.type == "expansion" then
        self:SelectExpansion(item.id, scrollTo or item.scrollTo)
    elseif item.type == "category" then
        self:SelectCategory(item.id, scrollTo or item.scrollTo)
    elseif item.type == "chain" then
        self:SelectChain(item.id, scrollTo or item.scrollTo)
    end
end

function BtWQuestsMixin:SelectFromHistory()
    local item = self.History[self.HistoryIndex]
    
    if item.type == "chain" then
        self:SelectChain(item.id, item.scrollTo, true)
    elseif item.type == "category" then
        self:SelectCategory(item.id, item.scrollTo, true)
    elseif item.type == "expansion" then
        self:SelectExpansion(item.id, item.scrollTo, true)
    end
end
function BtWQuestsMixin:Back()
    if self.HistoryIndex > 1 then
        self:UpdateCurrentHistory()
        
        self.HistoryIndex = self.HistoryIndex - 1
        
        self:SelectFromHistory()
    
        self:UpdateHistoryButtons()
    end
end
function BtWQuestsMixin:Forward()
    if self.HistoryIndex < #self.History then
        self:UpdateCurrentHistory()
        
        self.HistoryIndex = self.HistoryIndex + 1
        
        self:SelectFromHistory()
    
        self:UpdateHistoryButtons()
    end
end
function BtWQuestsMixin:Here()
    local item = BtWQuestsDatabase:GetMapItemByID(C_Map.GetBestMapForUnit("player"), self:GetCharacter())

    if item == nil then
        self.NavHere:Disable()
    else
        self:SelectItem(item)
    end
end
function BtWQuestsMixin:ZoomOut()
    self:Back()
    
    self.Tooltip:Hide();
end
function BtWQuestsMixin:GetCurrentView()
    if self.Chain:IsShown() then
        return {
            type = "chain",
            id = self:GetChain(),
            scrollTo = {
                type = "coords",
                x = self.Chain.Scroll:GetHorizontalScroll(),
                y = self.Chain.Scroll:GetVerticalScroll(),
            }
        };
    elseif self:GetCategory() ~= nil then
        return {
            type = "category",
            id = self:GetCategory(),
            scrollTo = {
                type = "coords",
                x = self.Category.Scroll:GetHorizontalScroll(),
                y = self.Category.Scroll:GetVerticalScroll(),
            }
        };
    else
        return {
            type = "expansion",
            id = self:GetExpansion(),
            scrollTo = {
                type = "coords",
                x = self.Category.Scroll:GetHorizontalScroll(),
                y = self.Category.Scroll:GetVerticalScroll(),
            }
        };
    end
end
function BtWQuestsMixin:AddCurrentToHistory()
    local last = self.History[self.HistoryIndex]
    local current = self:GetCurrentView()
    
    if last == nil or current.type ~= last.type or current.id ~= last.id then
        self.HistoryIndex = self.HistoryIndex + 1

        while self.History[self.HistoryIndex] do
            table.remove(self.History, self.HistoryIndex)
        end

        table.insert(self.History, current);
    end
    
    self:UpdateHistoryButtons()
end
function BtWQuestsMixin:UpdateCurrentHistory()
    self.History[self.HistoryIndex] = self:GetCurrentView();
end
function BtWQuestsMixin:UpdateHistoryButtons()
    self.NavBack:SetEnabled(self.HistoryIndex > 1)
    self.NavForward:SetEnabled(self.HistoryIndex < #self.History)
end
function BtWQuestsMixin:UpdateHereButton()
    self.NavHere:SetEnabled(BtWQuestsDatabase:GetMapItemByID(C_Map.GetBestMapForUnit("player"), self:GetCharacter()) ~= nil)
end

function BtWQuestsMixin:DisplayExpansionList(scrollTo)
	self.Chain:Hide()
	self.Category:Hide()
    self.ExpansionList:Show()
    
    local items = BtWQuestsDatabase:GetExpansionList(self:GetCharacter())

    if self.ExpansionScroll == nil then
        self.ExpansionScroll = #items - 2
    end

    if self.ExpansionScroll > #items - 2 then
        self.ExpansionScroll = #items - 2
    end
    if self.ExpansionScroll < 1 then
        self.ExpansionScroll = 1
    end

    for i=1,3 do
        local item = items[self.ExpansionScroll - 1 + i]
        local expansion = self.ExpansionList.Expansions[i]
        if item ~= nil then
            expansion:Set(item)
            expansion:Show()
        else
            expansion:Hide()
        end
    end

    local source = self.ExpansionList.Expansions[1]
    if #items == 1 then
        source:ClearAllPoints()
        source:SetPoint("BOTTOM", 0, 7)
    elseif #items == 2 then
        source:ClearAllPoints()
        source:SetPoint("BOTTOMRIGHT", self.ExpansionList, "BOTTOM", 0, 7)
    else
        source:ClearAllPoints()
        source:SetPoint("BOTTOMLEFT", 48, 7)
    end
end
function BtWQuestsMixin:DisplayItemList(items, scrollTo)
    local gridView = BtWQuestSettingsData:GetValue("gridView")

	self.categoryItemPool:ReleaseAll();
    local questSelect = self.Category;
    
    local character = self:GetCharacter()
    self.Tooltip.character = character
    
	self.Chain:Hide();
    self.ExpansionList:Hide()
	questSelect:Show();
    
	local scrollFrame = questSelect.Scroll.Child;
    local scrollToButton
    
    local startX = 12
    local startY = -10
	local i = 1;
    local index = 1;
    local gridIndex = 1
    local previousButton = nil

    local categoryButton
    for _,item in ipairs(items) do
        if item:GetType() == "header" then
            categoryButton = self.categoryItemPool:Acquire("BtWQuestsCategoryHeaderTemplate")
            if previousButton then
                categoryButton:SetPoint("TOP", previousButton, "BOTTOM", 0, -15)
                categoryButton:SetPoint("LEFT", 5, 0)
            else
                categoryButton:SetPoint("TOPLEFT", 5, -5)
            end
            gridIndex = 1
        elseif gridView then
            categoryButton = self.categoryItemPool:Acquire("BtWQuestsCategoryGridItemTemplate")
            if previousButton then
                if (gridIndex - 1) % 4 == 0 then
                    categoryButton:SetPoint("TOP", previousButton, "BOTTOM", 0, 0)
                    categoryButton:SetPoint("LEFT", 5, 0)
                else
                    categoryButton:SetPoint("LEFT", previousButton, "RIGHT", 0, 0)
                end
            else
                categoryButton:SetPoint("TOPLEFT", 5, -5)
            end
            gridIndex = gridIndex + 1
        else
            categoryButton = self.categoryItemPool:Acquire("BtWQuestsCategoryListItemTemplate")
        
            if previousButton then
                categoryButton:SetPoint("TOP", previousButton, "BOTTOM", 0, 0)
            else
                categoryButton:SetPoint("TOPLEFT", 5, -5)
            end
        end

        categoryButton:Set(item)
        categoryButton:Show()

        if type(scrollTo) == "number" and index == scrollTo then
            scrollToButton = categoryButton
        elseif type(scrollTo) == "table" and item:EqualsItem(scrollTo) then
            scrollToButton = categoryButton
        end

        previousButton = categoryButton
        index = index + 1
    end

    -- local item = expansion:GetItem(i)
    
    -- if item == nil then -- Somehow selected an empty expansion, probably means all the BtWQuests modules are disabled
    --     print(BTWQUESTS_NO_EXPANSION_ERROR)
    -- end

    -- while item do
    --     if not item:GetSkip() and item:GetVisible() then
    --         local categoryButton = self.categoryItemPool:Acquire();

    --         categoryButton:Set(item)
            
    --         if previousButton then
    --             categoryButton:SetPoint("TOP", previousButton, "BOTTOM", 0, 0)
    --         else
    --             categoryButton:SetPoint("TOPLEFT", 5, -5)
    --         end
            
    --         categoryButton:Show()

    --         if type(scrollTo) == "number" and index == scrollTo then
    --             scrollToButton = categoryButton
    --         elseif type(scrollTo) == "table" and item:EqualsItem(scrollTo) then
    --             scrollToButton = categoryButton
    --         end

    --         previousButton = categoryButton

    --         index = index + 1;
    --     end

    --     i = i + 1
    --     item = expansion:GetItem(i)
    -- end

    if type(scrollTo) == "table" and scrollTo.type == "coords" then
        questSelect.Scroll:UpdateScrollChildRect()
        -- questSelect.Scroll:SetHorizontalScroll(scrollTo.x)
        questSelect.Scroll:SetVerticalScroll(scrollTo.y)
    elseif scrollTo ~= false then
        if scrollToButton then
            questSelect.Scroll:UpdateScrollChildRect()
            questSelect.Scroll:SetVerticalScroll(-select(5, scrollToButton:GetPoint("TOP")) - (questSelect.Scroll:GetHeight()/2) + 24)
        else
            questSelect.Scroll:SetVerticalScroll(0)
        end
    end

    ShowUIPanel(self)
end
function BtWQuestsMixin:DisplayCurrentExpansion(scrollTo)
    local categoryHeaders = BtWQuestSettingsData:GetValue("categoryHeaders")
    local filterCompleted = BtWQuestSettingsData:GetValue("filterCompleted")
    local filterIgnored = BtWQuestSettingsData:GetValue("filterIgnored")

    local expansion = BtWQuestsDatabase:GetExpansion(self:GetExpansion(), self:GetCharacter())
    local items = expansion:GetItemList(not categoryHeaders, filterCompleted, filterIgnored)
    if #items == 0 then -- Somehow selected an empty expansion, probably means all the BtWQuests modules are disabled
        print(BTWQUESTS_NO_EXPANSION_ERROR)
    end
    self:DisplayItemList(items, scrollTo)
end
function BtWQuestsMixin:DisplayCurrentCategory(scrollTo)
    local categoryHeaders = BtWQuestSettingsData:GetValue("categoryHeaders")
    local filterCompleted = BtWQuestSettingsData:GetValue("filterCompleted")
    local filterIgnored = BtWQuestSettingsData:GetValue("filterIgnored")

    local category = BtWQuestsDatabase:GetCategory(self:GetCategory(), self:GetCharacter())
    local items = category:GetItemList(not categoryHeaders, filterCompleted, filterIgnored)
    self:DisplayItemList(items, scrollTo)
end
function BtWQuestsMixin:DisplayCurrentChain(scrollTo, zoom)
	local chain = self.Chain;
    
	self.Category:Hide();
    self.ExpansionList:Hide()
    chain:Show();
    
    -- chain.Scroll:SetCharacter(self:GetCharacter())
    chain.Scroll:SetChain(self:GetChain(), scrollTo, zoom)

    ShowUIPanel(self)
end
function BtWQuestsMixin:UpdateCurrentChain()
    local chain = self.Chain
    
    if chain:IsShown() then
        chain.Scroll:Update()
    end
end

local function ChainItemPool_HideAndClearAnchors(framePool, frame)
    FramePool_HideAndClearAnchors(framePool, frame)
    
    if frame.backgroundLinePool then
        frame.backgroundLinePool:ReleaseAll();
    end
end

tinsert(UISpecialFrames, "BtWQuestsFrame") 
function BtWQuestsMixin:OnLoad()
    self:RegisterEvent("ADDON_LOADED")
    self:RegisterEvent("QUEST_LOG_UPDATE")

    self:RegisterEvent("ZONE_CHANGED")
    self:RegisterEvent("ZONE_CHANGED_INDOORS")
    self:RegisterEvent("ZONE_CHANGED_NEW_AREA")
    
    self:SetAttribute("UIPanelLayout-defined", true)
    self:SetAttribute("UIPanelLayout-enabled", true)
    self:SetAttribute("UIPanelLayout-area", "left")
    self:SetAttribute("UIPanelLayout-pushable", 0)
    self:SetAttribute("UIPanelLayout-width", 830)
    self:SetAttribute("UIPanelLayout-whileDead", true)
    
	self.TitleText:SetText(BTWQUESTS_QUEST_JOURNAL);
    SetPortraitToTexture(self.portrait, "Interface\\QuestFrame\\UI-QuestLog-BookIcon");
    
    -- Updated the NineSlice frame for our extra buttons
    self.NineSlice.TopLeftCorner:SetTexture("Interface\\Addons\\BtWQuests\\UI-Frame-Metal")
    self.NineSlice.TopLeftCorner:SetWidth(196)
    self.NineSlice.TopLeftCorner:SetTexCoord(0, 0.3828125, 0, 0.2578125)
    
    self.NineSlice.TopRightCorner:SetTexture("Interface\\Addons\\BtWQuests\\UI-Frame-Metal")
    self.NineSlice.TopRightCorner:SetTexCoord(0, 0.2578125, 0.2578125, 0.515625)

    self.NineSlice.TopEdge:SetPoint("TOPRIGHT", self.CharacterDropDown, "TOPLEFT", 0, 0);
    
    self.categoryItemPool = CreatePoolCollection()--CreateFramePool("BUTTON", self.Category.Scroll.Child, "BtWQuestsCategoryButtonTemplate");
	self.categoryItemPool:CreatePool("BUTTON", self.Category.Scroll.Child, "BtWQuestsCategoryHeaderTemplate");
    self.categoryItemPool:CreatePool("BUTTON", self.Category.Scroll.Child, "BtWQuestsCategoryListItemTemplate");
	self.categoryItemPool:CreatePool("BUTTON", self.Category.Scroll.Child, "BtWQuestsCategoryGridItemTemplate");
    
    self.chainItemPool = CreateFramePool("BUTTON", self.Chain.Scroll.Child, "BtWQuestsChainItemButtonTemplate", ChainItemPool_HideAndClearAnchors);
    
    self.ExpansionScroll = nil
    self.HistoryIndex = 1
    self.History = {}
    
	-- LDB launcher
	local LDB = LibStub and LibStub("LibDataBroker-1.1", true)
	if LDB then
		BtWQuestsLauncher = LDB:NewDataObject("BtWQuests", {
			type = "launcher",
            label = "BtWQuests",
			icon = "Interface\\QuestFrame\\UI-QuestLog-BookIcon",
			OnClick = function(clickedframe, button)
				ToggleFrame(BtWQuestsFrame)
			end,
		})
	end
end
function BtWQuestsMixin:OnEvent(event, ...)
    if event == "ADDON_LOADED" then
        if ... == "BtWQuests" then
            -- hooksecurefunc("QuestObjectiveTracker_OnOpenDropDown", function (self)
            --     BtWQuests_AddOpenChainMenuItem(self, self.activeFrame.id)
            -- end)
            -- hooksecurefunc(QuestMapQuestOptionsDropDown, "initialize", function (self)
            --     BtWQuests_AddOpenChainMenuItem(self, self.questID)
            -- end)

            WorldMapFrame:AddDataProvider(CreateFromMixins(BtWQuestsQuestDataProviderMixin));
        end
    elseif event == "QUEST_LOG_UPDATE" then
        if BtWQuestsCharacters ~= nil then
            BtWQuestsCharacters:UpdatePlayer()
        end
    elseif event == "ZONE_CHANGED" or event == "ZONE_CHANGED_INDOORS" or event == "ZONE_CHANGED_NEW_AREA" then
        if self:IsShown() then
            self:UpdateHereButton()
        end
    end
end
function BtWQuestsMixin:Refresh()
    if self:GetChain() ~= nil then
        self.navBar:SetChain(self:GetChain())
        self:DisplayCurrentChain()
    elseif self:GetCategory() ~= nil then
        self.navBar:SetCategory(self:GetCategory())
        self:DisplayCurrentCategory(false)
    elseif self:GetExpansion() ~= nil then
        self.navBar:SetExpansion(self:GetExpansion())
        self:DisplayCurrentExpansion(false)
    else
        self.navBar:Reset()
        self:DisplayExpansionList(false)
    end
end
function BtWQuestsMixin:OnShow()
    PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN);
    
    self:UpdateHereButton()

    if not self.initialized then
        self:SelectCharacter(UnitName("player"), GetRealmName())

        self.navBar:EnableExpansions(BtWQuestsDatabase:HasMultipleExpansion())

        if self:GetExpansion() == nil and not BtWQuestsDatabase:HasMultipleExpansion() then -- Not guessed/set an expansion yet
            self:SetExpansion(BtWQuestsDatabase:GuessExpansion(self.Character))
            self:DisplayCurrentExpansion()
        end
        
        self.initialized = true
    else
        if self:GetChain() ~= nil then
            self:UpdateCurrentChain()
        elseif self:GetCategory() ~= nil then
            self:DisplayCurrentCategory()
        elseif self:GetExpansion() ~= nil then
            self:DisplayCurrentExpansion()
        else
            self:DisplayExpansionList()
        end
    end
end
function BtWQuestsMixin:OnHide(self)
	PlaySound(SOUNDKIT.IG_CHARACTER_INFO_CLOSE);
end

function BtWQuestsChainFrame_OnShow(self)
    self:RegisterEvent("QUEST_ACCEPTED")
    self:RegisterEvent("QUEST_AUTOCOMPLETE")
    self:RegisterEvent("QUEST_COMPLETE")
    self:RegisterEvent("QUEST_FINISHED")
    self:RegisterEvent("QUEST_TURNED_IN")
    self:RegisterEvent("QUEST_LOG_CRITERIA_UPDATE")
    self:RegisterEvent("QUEST_WATCH_LIST_CHANGED")
    self:RegisterEvent("QUEST_WATCH_UPDATE")
end
function BtWQuestsChainFrame_OnHide(self)
    self:UnregisterAllEvents()
end
function BtWQuestsChainFrame_OnEvent(self, ...)
    self:GetParent():UpdateCurrentChain()
end
function BtWQuestsChainFrameScrollFrame_OnUpdate(self)
    local mouseX, mouseY = GetCursorPosition()
    local scale = self:GetEffectiveScale()
    mouseX, mouseY = mouseX / scale, mouseY / scale
    
    local maxXScroll, maxYScroll = self:GetHorizontalScrollRange(), self:GetVerticalScrollRange()
    
    mouseX = min(max(mouseX - self.mouseX + self.scrollX, 0), maxXScroll)
    mouseY = min(max(mouseY - self.mouseY + self.scrollY, 0), maxYScroll)
    
    self:SetHorizontalScroll(mouseX)
    self:SetVerticalScroll(mouseY)
end

-- [[ Compatibility functions ]]
-- These functions use the character from BtWQuestsFrame
function BtWQuests_GetQuestName(id)
    return BtWQuestsDatabase:GetQuestName(id)
end
function BtWQuests_IsQuestCompleted(id)
    return BtWQuestsFrame:GetCharacter():IsQuestCompleted(id)
end
function BtWQuests_IsQuestActive(id)
    return BtWQuestsFrame:GetCharacter():IsQuestActive(id)
end

function BtWQuests_GetChainName(id)
    return BtWQuestsDatabase:GetChainName(id, BtWQuestsFrame:GetCharacter())
end
function BtWQuests_IsChainCompleted(id)
    return BtWQuestsFrame:GetCharacter():IsChainCompleted(id)
end
function BtWQuests_IsChainActive(id)
    return BtWQuestsFrame:GetCharacter():IsChainCompleted(id)
end

function BtWQuests_GetCategoryName(id)
    return BtWQuestsDatabase:GetCategoryName(id, BtWQuestsFrame:GetCharacter())
end
function BtWQuests_IsCategoryCompleted(id)
    return BtWQuestsFrame:GetCharacter():IsCategoryCompleted(id)
end
function BtWQuests_IsCategoryActive(id)
    return BtWQuestsFrame:GetCharacter():IsCategoryCompleted(id)
end

-- [[ Waypoint ]]
function BtWQuests_AddWaypoint(mapId, x, y, name)
    if TomTom and TomTom.AddWaypoint then
        TomTom:AddWaypoint(mapId, x, y, {
            title = name,
        })
    end
end
function BtWQuests_ShowMapWithWaypoint(mapId, x, y, name)
    BtWQuests_AddWaypoint(mapId, x, y, name)

    if not IsModifiedClick("CHATLINK") then
        OpenQuestLog(mapId)
    end
end

-- [[ Quest To Chain ]]
function BtWQuests_AddOpenChainMenuItem(self, questID)
    local item = BtWQuestsDatabase:GetQuestItem(questID, BtWQuestsCharacters:GetPlayer())
    if item then
        local info = UIDropDownMenu_CreateInfo()
        info.text = BTWQUESTS_OPEN_QUEST_CHAIN
        info.func = function(self, questID, item)
            BtWQuestsFrame:SelectCharacter(UnitName("player"), GetRealmName())
            BtWQuestsFrame:SelectItem(item.item)
        end
        info.arg1 = questID
        info.arg2 = item
        info.notCheckable = 1;
        info.checked = false;
        info.noClickSound = 1;
        UIDropDownMenu_AddButton(info, UIDROPDOWN_MENU_LEVEL)
    end
end

-- [[ Slash Command ]]
SLASH_BTWQUESTS1 = "/btwquests"
SlashCmdList["BTWQUESTS"] = function(msg)
    if msg == "minimap" then
        BtWQuestsMinimapButton_Toggle()
    else
        ToggleFrame(BtWQuestsFrame)
    end
end 


-- [[ Hyperlink Handling ]]

local function ChatFrame_Filter(self, event, msg, ...)
	msg = msg:gsub("%[btwquests:([^:]+):(%d+):([^:]+):([^%]]+)%]","|c%3|Hbtwquests:%1:%2|h[%4]|h|r");
    
	return false, msg, ...;
end

local events = {
	"CHAT_MSG_SAY",
	"CHAT_MSG_YELL",
	"CHAT_MSG_EMOTE",
	"CHAT_MSG_GUILD",
	"CHAT_MSG_OFFICER",
	"CHAT_MSG_PARTY",
	"CHAT_MSG_PARTY_LEADER",
	"CHAT_MSG_RAID",
	"CHAT_MSG_RAID_LEADER",
	"CHAT_MSG_RAID_WARNING",
	"CHAT_MSG_BATTLEGROUND",
	"CHAT_MSG_BATTLEGROUND_LEADER",
	"CHAT_MSG_WHISPER",
	"CHAT_MSG_WHISPER_INFORM",
	"CHAT_MSG_BN_WHISPER",
	"CHAT_MSG_BN_WHISPER_INFORM",
	"CHAT_MSG_BN_CONVERSATION",
	"CHAT_MSG_BN_INLINE_TOAST_BROADCAST",
	"CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM",
    "CHAT_MSG_CHANNEL",
    "CHAT_MSG_COMMUNITIES_CHANNEL",
};

for i, event in ipairs(events) do
	ChatFrame_AddMessageEventFilter(event, ChatFrame_Filter);
end

-- Rewrite correctly syntaxed links to something that is viable to send
function BtWQuests_InsertLink(link)
    if link then
        local _, _, color, type, text, name = string.find(link, "|c(%x*)|H([^:]+):([^|]+)|h%[([^%[%]]*)%]|h|r")
        if not color then
            _, _, type, text = string.find(link, "([^:]+):(.+)")
        end
        if type == "btwquests" then
            link = format("[%s:%s:%s:%s]", type, text, color, name)
        end
    end
    
    return ChatEdit_InsertLink(link)
end

function BtWQuests_TryInsertChatLink(link)
	if IsModifiedClick("CHATLINK") and link then
		return BtWQuests_InsertLink(link)
	end
end

-- Handles shift clicking btwquests links
local original_HandleModifiedItemClick = HandleModifiedItemClick
function HandleModifiedItemClick(link)
    if link and link:find("Hbtwquests") then
        if IsModifiedClick("CHATLINK") then
			BtWQuests_InsertLink(link)
		else
            BtWQuestsFrame:SelectFromLink(link)
		end
    else
        return original_HandleModifiedItemClick(link)
    end
end

-- Handles clicking btwquests links
local original_SetHyperlink = ItemRefTooltip.SetHyperlink
function ItemRefTooltip:SetHyperlink(link)
    if link:find("^btwquests") then
        if IsModifiedClick("CHATLINK") then
			BtWQuests_InsertLink(link)
		else
            BtWQuestsFrame:SelectFromLink(link)
		end
	else
		original_SetHyperlink(self, link);
	end
end