local _, GW = ...
local RoundDec = GW.RoundDec
local lerp = GW.lerp
local GetSetting = GW.GetSetting
local CommaValue = GW.CommaValue
local NotificationStateChanged = GW.NotificationStateChanged
local SetObjectiveNotification = GW.SetObjectiveNotification
local animations = GW.animations
local AddToAnimation = GW.AddToAnimation

local savedQuests = {}
local mapID = ""

local TRACKER_TYPE_COLOR = {}
GW.TRACKER_TYPE_COLOR = TRACKER_TYPE_COLOR
TRACKER_TYPE_COLOR["QUEST"] = {r = 221 / 255, g = 198 / 255, b = 68 / 255}
TRACKER_TYPE_COLOR["EVENT"] = {r = 240 / 255, g = 121 / 255, b = 37 / 255}
TRACKER_TYPE_COLOR["BONUS"] = {r = 240 / 255, g = 121 / 255, b = 37 / 255}
TRACKER_TYPE_COLOR["SCENARIO"] = {r = 171 / 255, g = 37 / 255, b = 240 / 255}
TRACKER_TYPE_COLOR["BOSS"] = {r = 240 / 255, g = 37 / 255, b = 37 / 255}
TRACKER_TYPE_COLOR["ACHIEVEMENT"] = {r = 37 / 255, g = 240 / 255, b = 172 / 255}

local function wiggleAnim(self)
    if self.animation == nil then
        self.animation = 0
    end
    if self.doingAnimation == true then
        return
    end
    self.doingAnimation = true
    AddToAnimation(
        self:GetName(),
        0,
        1,
        GetTime(),
        2,
        function()
            local prog = animations[self:GetName()]["progress"]

            self.flare:SetRotation(lerp(0, 1, prog))

            if prog < 0.25 then
                self.texture:SetRotation(lerp(0, -0.5, math.sin((prog / 0.25) * math.pi * 0.5)))
                self.flare:SetAlpha(lerp(0, 1, math.sin((prog / 0.25) * math.pi * 0.5)))
            end
            if prog > 0.25 and prog < 0.75 then
                self.texture:SetRotation(lerp(-0.5, 0.5, math.sin(((prog - 0.25) / 0.5) * math.pi * 0.5)))
            end
            if prog > 0.75 then
                self.texture:SetRotation(lerp(0.5, 0, math.sin(((prog - 0.75) / 0.25) * math.pi * 0.5)))
            end

            if prog > 0.25 then
                self.flare:SetAlpha(lerp(1, 0, ((prog - 0.25) / 0.75)))
            end
        end,
        nil,
        function()
            self.doingAnimation = false
        end
    )
end
GW.AddForProfiling("objectives", "wiggleAnim", wiggleAnim)

local function NewQuestAnimation(block)
    block.flare:Show()
    block.flare:SetAlpha(1)
    AddToAnimation(
        block:GetName() .. "flare",
        0,
        1,
        GetTime(),
        1,
        function(step)
            block:SetWidth(300 * step)
            block.flare:SetSize(300 * (1 - step), 300 * (1 - step))
            block.flare:SetRotation(2 * step)

            if step > 0.75 then
                block.flare:SetAlpha((step - 0.75) / 0.25)
            end
        end,
        nil,
        function()
            block.flare:Hide()
        end
    )
end
GW.NewQuestAnimation = NewQuestAnimation

local function loadQuestButtons()
    local actionButton
    for i = 1, 25 do
        actionButton = CreateFrame("Button", "GwQuestItemButton" .. i, GwQuestTracker, "GwQuestItemTemplate")
        actionButton.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
        actionButton.NormalTexture:SetTexture(nil)
        actionButton:RegisterForClicks("AnyUp")
        actionButton:SetScript("OnShow", QuestObjectiveItem_OnHide)
        actionButton:SetScript("OnHide", QuestObjectiveItem_OnHide)
        actionButton:SetScript("OnEnter", QuestObjectiveItem_OnEnter)
    end

    actionButton = CreateFrame("Button", "GwBonusItemButton", GwQuestTracker, "GwQuestItemTemplate")
    actionButton.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
    actionButton.NormalTexture:SetTexture(nil)
    actionButton:RegisterForClicks("AnyUp")
    actionButton:SetScript("OnShow", QuestObjectiveItem_OnHide)
    actionButton:SetScript("OnHide", QuestObjectiveItem_OnHide)
    actionButton:SetScript("OnEnter", QuestObjectiveItem_OnEnter)

    actionButton = CreateFrame("Button", "GwScenarioItemButton", GwQuestTracker, "GwQuestItemTemplate")
    actionButton.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
    actionButton.NormalTexture:SetTexture(nil)
    actionButton:RegisterForClicks("AnyUp")
    actionButton:SetScript("OnShow", QuestObjectiveItem_OnHide)
    actionButton:SetScript("OnHide", QuestObjectiveItem_OnHide)
    actionButton:SetScript("OnEnter", QuestObjectiveItem_OnEnter)
end
GW.AddForProfiling("objectives", "loadQuestButtons", loadQuestButtons)

local function ParseSimpleObjective(text)
    local itemName, numItems, numNeeded = string.match(text, "(.*):%s*([%d]+)%s*/%s*([%d]+)")

    if itemName == nil then
        numItems, numNeeded, _ = string.match(text, "(%d+)/(%d+) (%S+)")
    end
    local ndString = ""

    if numItems ~= nil then
        ndString = numItems
    end

    if numNeeded ~= nil then
        ndString = ndString .. "/" .. numNeeded
    end

    return string.gsub(text, ndString, "")
end
GW.ParseSimpleObjective = ParseSimpleObjective

local function ParseCriteria(quantity, totalQuantity, criteriaString)
    if quantity ~= nil and totalQuantity ~= nil and criteriaString ~= nil then
        return string.format("%d/%d %s", quantity, totalQuantity, criteriaString)
    end

    return criteriaString
end
GW.ParseCriteria = ParseCriteria

local function ParseObjectiveString(block, text, objectiveType, quantity)
    if objectiveType == "progressbar" then
        block.StatusBar:SetMinMaxValues(0, 100)
        block.StatusBar:SetValue(quantity)
        block.StatusBar:Show()
        block.StatusBar.precentage = true
        return true
    end
    block.StatusBar.precentage = false
    local _, numItems, numNeeded = string.match(text, "(.*):%s*([%d]+)%s*/%s*([%d]+)")
    if numItems == nil then
        numItems, numNeeded, _ = string.match(text, "(%d+)/(%d+) (%S+)")
    end
    numItems = tonumber(numItems)
    numNeeded = tonumber(numNeeded)

    if numItems ~= nil and numNeeded ~= nil and numNeeded > 1 and numItems < numNeeded then
        block.StatusBar:Show()
        block.StatusBar:SetMinMaxValues(0, numNeeded)
        block.StatusBar:SetValue(numItems)
        block.progress = numItems / numNeeded
        return true
    end
    return false
end
GW.ParseObjectiveString = ParseObjectiveString

local function FormatObjectiveNumbers(text)
    local itemName, numItems, numNeeded = string.match(text, "(.*):%s*([%d]+)%s*/%s*([%d]+)")

    if itemName == nil then
        numItems, numNeeded, itemName = string.match(text, "(%d+)/(%d+) ((.*))")
    end
    numItems = tonumber(numItems)
    numNeeded = tonumber(numNeeded)

    if numItems ~= nil and numNeeded ~= nil then
        return CommaValue(numItems) .. " / " .. CommaValue(numNeeded) .. " " .. itemName
    end
    return text
end
GW.FormatObjectiveNumbers = FormatObjectiveNumbers

local function setBlockColor(block, string)
    block.color = TRACKER_TYPE_COLOR[string]
end
GW.AddForProfiling("objectives", "setBlockColor", setBlockColor)

local function statusBar_OnShow(self)
    local f = self:GetParent()
    if not f then
        return
    end
    f:SetHeight(50)
    f.statusbarBg:Show()
end
GW.AddForProfiling("objectives", "statusBar_OnShow", statusBar_OnShow)

local function statusBar_OnHide(self)
    local f = self:GetParent()
    if not f then
        return
    end
    f:SetHeight(20)
    f.statusbarBg:Hide()
end
GW.AddForProfiling("objectives", "statusBar_OnHide", statusBar_OnHide)

local function statusBarSetValue(self)
    local f = self:GetParent()
    if not f then
        return
    end
    local _, mx = self:GetMinMaxValues()
    local v = self:GetValue()
    local width = math.max(1, math.min(10, 10 * ((v / mx) / 0.1)))
    f.StatusBar.Spark:SetPoint("RIGHT", self, "LEFT", 280 * (v / mx), 0)
    f.StatusBar.Spark:SetWidth(width)
    if self.precentage == nil or self.precentage == false then
        self.progress:SetText(v .. " / " .. mx)
    else
        self.progress:SetText(math.floor((v / mx) * 100) .. "%")
    end
end
GW.AddForProfiling("objectives", "statusBarSetValue", statusBarSetValue)

local function CreateObjectiveNormal(name, parent)
    local f = CreateFrame("Frame", name, parent, "GwQuesttrackerObjectiveNormal")
    f.ObjectiveText:SetFont(UNIT_NAME_FONT, 12)
    f.ObjectiveText:SetShadowOffset(-1, 1)
    f.StatusBar.progress:SetFont(UNIT_NAME_FONT, 11)
    f.StatusBar.progress:SetShadowOffset(-1, 1)
    if f.StatusBar.animationOld == nil then
        f.StatusBar.animationOld = 0
    end
    f.StatusBar:SetScript("OnShow", statusBar_OnShow)
    f.StatusBar:SetScript("OnHide", statusBar_OnHide)
    hooksecurefunc(f.StatusBar, "SetValue", statusBarSetValue)

    return f
end
GW.CreateObjectiveNormal = CreateObjectiveNormal

local function CreateTrackerObject(name, parent)
    local f = CreateFrame("Button", name, parent, "GwQuesttrackerObject")
    f.Header:SetFont(UNIT_NAME_FONT, 14)
    f.SubHeader:SetFont(UNIT_NAME_FONT, 12)
    f.Header:SetShadowOffset(1, -1)
    f.SubHeader:SetShadowOffset(1, -1)
    f:SetScript(
        "OnEnter",
        function(self)
            self.hover:Show()
            if self.objectiveBlocks == nil then
                self.objectiveBlocks = {}
            end
            for k, v in pairs(self.objectiveBlocks) do
                v.StatusBar.progress:Show()
            end
            AddToAnimation(
                self:GetName() .. "hover",
                0,
                1,
                GetTime(),
                0.2,
                function(step)
                    self.hover:SetAlpha(step - 0.3)
                    self.hover:SetTexCoord(0, step, 0, 1)
                end
            )
        end
    )
    f:SetScript(
        "OnLeave",
        function(self)
            self.hover:Hide()
            if self.objectiveBlocks == nil then
                self.objectiveBlocks = {}
            end
            for k, v in pairs(self.objectiveBlocks) do
                v.StatusBar.progress:Hide()
            end
            if animations[self:GetName() .. "hover"] ~= nil then
                animations[self:GetName() .. "hover"]["complete"] = true
            end
        end
    )
    f.clickHeader:SetScript(
        "OnEnter",
        function(self)
            self.oldColor = {}
            self.oldColor.r, self.oldColor.g, self.oldColor.b = self:GetParent().Header:GetTextColor()
            self:GetParent().Header:SetTextColor(self.oldColor.r * 2, self.oldColor.g * 2, self.oldColor.b * 2)
        end
    )
    f.clickHeader:SetScript(
        "OnLeave",
        function(self)
            if self.oldColor == nil then
                return
            end
            self:GetParent().Header:SetTextColor(self.oldColor.r, self.oldColor.g, self.oldColor.b)
        end
    )
    f.turnin:SetScript(
        "OnShow",
        function(self)
            self:SetScript("OnUpdate", wiggleAnim)
        end
    )
    f.turnin:SetScript(
        "OnHide",
        function(self)
            self:SetScript("OnUpdate", nil)
        end
    )

    return f
end
GW.CreateTrackerObject = CreateTrackerObject

local function getObjectiveBlock(self, index)
    if _G[self:GetName() .. "GwQuestObjective" .. index] ~= nil then
        return _G[self:GetName() .. "GwQuestObjective" .. index]
    end

    if self.objectiveBlocksNum == nil then
        self.objectiveBlocksNum = 0
    end
    if self.objectiveBlocks == nil then
        self.objectiveBlocks = {}
    end

    self.objectiveBlocksNum = self.objectiveBlocksNum + 1

    local newBlock = CreateObjectiveNormal(self:GetName() .. "GwQuestObjective" .. self.objectiveBlocksNum, self)
    newBlock:SetParent(self)
    self.objectiveBlocks[#self.objectiveBlocks] = newBlock
    if self.objectiveBlocksNum == 1 then
        newBlock:SetPoint("TOPRIGHT", self, "TOPRIGHT", 0, -25)
    else
        newBlock:SetPoint(
            "TOPRIGHT",
            _G[self:GetName() .. "GwQuestObjective" .. (self.objectiveBlocksNum - 1)],
            "BOTTOMRIGHT",
            0,
            0
        )
    end

    newBlock.StatusBar:SetStatusBarColor(self.color.r, self.color.g, self.color.b)

    return newBlock
end
GW.AddForProfiling("objectives", "getObjectiveBlock", getObjectiveBlock)

local function getBlock(blockIndex)
    if _G["GwQuestBlock" .. blockIndex] ~= nil then
        return _G["GwQuestBlock" .. blockIndex]
    end

    local newBlock = CreateTrackerObject("GwQuestBlock" .. blockIndex, GwQuesttrackerContainerQuests)
    newBlock:SetParent(GwQuesttrackerContainerQuests)

    if blockIndex == 1 then
        newBlock:SetPoint("TOPRIGHT", GwQuesttrackerContainerQuests, "TOPRIGHT", 0, -20)
    else
        newBlock:SetPoint("TOPRIGHT", _G["GwQuestBlock" .. (blockIndex - 1)], "BOTTOMRIGHT", 0, 0)
    end
    newBlock.clickHeader:Show()
    setBlockColor(newBlock, "QUEST")
    newBlock.Header:SetTextColor(newBlock.color.r, newBlock.color.g, newBlock.color.b)
    newBlock.hover:SetVertexColor(newBlock.color.r, newBlock.color.g, newBlock.color.b)
    return newBlock
end
GW.AddForProfiling("objectives", "getBlock", getBlock)

local function addObjective(block, text, finished, objectiveIndex)
    if finished == true then
        return
    end
    local objectiveBlock = getObjectiveBlock(block, objectiveIndex)

    if text then
        objectiveBlock:Show()
        objectiveBlock.ObjectiveText:SetText(text)
        if finished then
            objectiveBlock.ObjectiveText:SetTextColor(0.8, 0.8, 0.8)
        else
            objectiveBlock.ObjectiveText:SetTextColor(1, 1, 1)
        end

        if objectiveType == "progressbar" or ParseObjectiveString(objectiveBlock, text) then
            if objectiveType == "progressbar" then
                objectiveBlock.StatusBar:Show()
                objectiveBlock.StatusBar:SetMinMaxValues(0, 100)
                objectiveBlock.StatusBar:SetValue(GetQuestProgressBarPercent(block.questID))
            end
        else
            objectiveBlock.StatusBar:Hide()
        end
        local h = 20
        if objectiveBlock.StatusBar:IsShown() then
            h = 50
        end
        block.height = block.height + h
        block.numObjectives = block.numObjectives + 1
    end
end
GW.AddForProfiling("objectives", "addObjective", addObjective)

local function updateQuestObjective(block, numObjectives, isComplete, title)
    local addedObjectives = 1
    for objectiveIndex = 1, numObjectives do
        local text, _, finished = GetQuestLogLeaderBoard(objectiveIndex, block.questLogIndex)
        if not finished then
            addObjective(block, text, finished, addedObjectives)
            addedObjectives = addedObjectives + 1
        end
    end
end
GW.AddForProfiling("objectives", "updateQuestObjective", updateQuestObjective)

local function UpdateQuestItem(button, questLogIndex)
    if InCombatLockdown() then
        return
    end

    if button == nil then
        return
    end

    local link, item, charges, _ = GetQuestLogSpecialItemInfo(questLogIndex)

    if item == nil then
        button:Hide()
        return
    end

    button:SetID(questLogIndex)

    button:SetAttribute("type", "item")
    button:SetAttribute("item", GetItemInfo(link))

    button.charges = charges
    button.rangeTimer = -1
    SetItemButtonTexture(button, item)
    SetItemButtonCount(button, charges)

    QuestObjectiveItem_UpdateCooldown(button)
    button:Show()
end
GW.UpdateQuestItem = UpdateQuestItem

local function updatePOI(questID, questLogIndex)
    PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON)

    if (IsQuestWatched(questLogIndex)) then
        if (IsShiftKeyDown()) then
            QuestObjectiveTracker_UntrackQuest(nil, questID)
            return
        end
    else
        AddQuestWatch(questLogIndex, true)
    end
    SetSuperTrackedQuestID(questID)
   -- WorldMapFrame_OnUserChangedSuperTrackedQuest(questID)
end
GW.AddForProfiling("objectives", "updatePOI", updatePOI)

local function updateQuest(block, questWatchId)
    block.height = 25
    block.numObjectives = 0
    block.turnin:Hide()

    local questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, startEvent, isAutoComplete, _ =
        GetQuestWatchInfo(questWatchId)

    if questID then
        if savedQuests[questID] == nil then
            NewQuestAnimation(block)
            savedQuests[questID] = true
        end

        block.questID = questID
        block.questLogIndex = questLogIndex

        block.Header:SetText(title)

        --Quest item

        UpdateQuestItem(_G["GwQuestItemButton" .. questWatchId], questLogIndex)

        if isComplete and isComplete < 0 then
            isComplete = false
            questFailed = true
        elseif numObjectives == 0 and GetMoney() >= requiredMoney and not startEvent then
            isComplete = true
        end

        updateQuestObjective(block, numObjectives, isComplete, title)

        if requiredMoney ~= nil and requiredMoney > GetMoney() then
            addObjective(
                block,
                GetMoneyString(GetMoney()) .. " / " .. GetMoneyString(requiredMoney),
                finished,
                block.numObjectives + 1
            )
        end

        if isComplete then
            if isAutoComplete then
                addObjective(block, QUEST_WATCH_CLICK_TO_COMPLETE, false, block.numObjectives + 1)
                block.turnin:Show()
                block.turnin:SetScript(
                    "OnClick",
                    function()
                        ShowQuestComplete(questLogIndex)
                    end
                )
            else
                local completionText = GetQuestLogCompletionText(questLogIndex)

                if (completionText) then
                    addObjective(block, completionText, false, block.numObjectives + 1)
                else
                    addObjective(block, QUEST_WATCH_QUEST_READY, false, block.numObjectives + 1)
                end
            end
        end

        block.clickHeader:SetScript(
            "OnClick",
            function()
                updatePOI(questID, questLogIndex)
            end
        )
        block:SetScript(
            "OnClick",
            function()
                QuestLogPopupDetailFrame_Show(questLogIndex)
            end
        )
    end
    if block.objectiveBlocks == nil then
        block.objectiveBlocks = {}
    end

    for i = block.numObjectives + 1, 20 do
        if _G[block:GetName() .. "GwQuestObjective" .. i] ~= nil then
            _G[block:GetName() .. "GwQuestObjective" .. i]:Hide()
        end
    end
    block.height = block.height + 5
    block:SetHeight(block.height)
end
GW.AddForProfiling("objectives", "updateQuest", updateQuest)

local function updateQuestItemPositions(index, height)
    if _G["GwQuestItemButton" .. index] == nil then
        return
    end

    if InCombatLockdown() then
        return
    end

    height = height + GwQuesttrackerContainerScenario:GetHeight() + 25
    height = height + GwQuesttrackerContainerAchievement:GetHeight()

    if GwObjectivesNotification:IsShown() then
        height = height + 70
    end

    _G["GwQuestItemButton" .. index]:SetPoint("TOPLEFT", GwQuestTracker, "TOPRIGHT", -330, -height)
end
GW.AddForProfiling("objectives", "updateQuestItemPositions", updateQuestItemPositions)

local function updateExtraQuestItemPositions()
    if GwBonusItemButton == nil or GwScenarioItemButton == nil then
        return
    end

    if InCombatLockdown() then
        return
    end

    local height = 0

    if GwObjectivesNotification:IsShown() then
        height = height + 70
    end

    GwScenarioItemButton:SetPoint("TOPLEFT", GwQuestTracker, "TOPRIGHT", -330, -height)

    height =
        height + GwQuesttrackerContainerScenario:GetHeight() + GwQuesttrackerContainerQuests:GetHeight() +
        GwQuesttrackerContainerAchievement:GetHeight() +
        GwQuesttrackerContainerAchievement:GetHeight()

    GwBonusItemButton:SetPoint("TOPLEFT", GwQuestTracker, "TOPRIGHT", -330, -height + -25)
end
GW.AddForProfiling("objectives", "updateExtraQuestItemPositions", updateExtraQuestItemPositions)

--[[
function gwRequestQustlogUpdate()
    updateQuestLogLayout()
end
--]]
local function QuestTrackerLayoutChanged()
    updateExtraQuestItemPositions()
    GwQuestTrackerScroll:SetSize(
        400,
        GwQuesttrackerContainerBonusObjectives:GetHeight() + GwQuesttrackerContainerQuests:GetHeight()
    )
end
GW.QuestTrackerLayoutChanged = QuestTrackerLayoutChanged

local function updateQuestLogLayout(intent, ...)
    local savedHeight = 1
    GwQuestHeader:Hide()

    local numQuests = GetNumQuestWatches()
    if GwQuesttrackerContainerQuests.collapsed == true then
        GwQuestHeader:Show()
        numQuests = 0
        savedHeight = 20
    end

    for i = 1, numQuests do
        if i == 1 then
            savedHeight = 20
        end
        GwQuestHeader:Show()
        local block = getBlock(i)
        if block == nil then
            return
        end
        updateQuest(block, i)
        block:Show()
        updateQuestItemPositions(i, savedHeight)

        savedHeight = savedHeight + block.height
    end
    GwQuesttrackerContainerQuests:SetHeight(savedHeight)
    for i = numQuests + 1, 25 do
        if _G["GwQuestBlock" .. i] ~= nil then
            _G["GwQuestBlock" .. i]:Hide()
            UpdateQuestItem(_G["GwQuestItemButton" .. i], 0)
        end
    end

    QuestTrackerLayoutChanged()
end
GW.AddForProfiling("objectives", "updateQuestLogLayout", updateQuestLogLayout)

local function tracker_OnEvent(self, event, ...)
    updateQuestLogLayout(...)
end
GW.AddForProfiling("objectives", "tracker_OnEvent", tracker_OnEvent)

local function trackerNotification_OnEvent(self, event)
	mapID = C_Map.GetBestMapForUnit("player")
end
GW.AddForProfiling("objectives", "trackerNotification_OnEvent", trackerNotification_OnEvent)

local function tracker_OnUpdate()
    if GwQuestTracker.trot < GetTime() then
        local state = GwObjectivesNotification.shouldDisplay

        GwQuestTracker.trot = GetTime() + 1
        GW.SetObjectiveNotification(mapID)

        if state ~= GwObjectivesNotification.shouldDisplay then
            state = GwObjectivesNotification.shouldDisplay
            GW.NotificationStateChanged(state)
        end
    end
end
GW.AddForProfiling("objectives", "tracker_OnUpdate", tracker_OnUpdate)

local function bonus_OnEnter(self)
    GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT", 0, 0)
    GameTooltip:ClearLines()
    GameTooltip:SetText(RoundDec(self.progress * 100, 0) .. "%")
    GameTooltip:Show()
end
GW.AddForProfiling("objectives", "bonus_OnEnter", bonus_OnEnter)

local function LoadQuestTracker()
    ObjectiveTrackerFrame:Hide()
    ObjectiveTrackerFrame:SetScript(
        "OnShow",
        function()
            ObjectiveTrackerFrame:Hide()
        end
    )

    local fTracker = CreateFrame("Frame", "GwQuestTracker", UIParent, "GwQuestTracker")

    local fTraScr = CreateFrame("ScrollFrame", "GwQuestTrackerScroll", fTracker, "GwQuestTrackerScroll")
    fTraScr:SetScript(
        "OnMouseWheel",
        function(self, delta)
            delta = -delta * 15
            local s = math.max(0, self:GetVerticalScroll() + delta)
            self:SetVerticalScroll(s)
        end
    )

    local fScroll = CreateFrame("Frame", "GwQuestTrackerScrollChild", fTraScr, "GwQuestTracker")

    local fNotify = CreateFrame("Frame", "GwObjectivesNotification", fTracker, "GwObjectivesNotification")
    fNotify.animatingState = false
    fNotify.animating = false
    fNotify.title:SetFont(UNIT_NAME_FONT, 14)
    fNotify.title:SetShadowOffset(1, -1)
    fNotify.desc:SetFont(UNIT_NAME_FONT, 12)
    fNotify.desc:SetShadowOffset(1, -1)
    fNotify.bonusbar.bar:SetOrientation("VERTICAL")
    fNotify.bonusbar.bar:SetMinMaxValues(0, 1)
    fNotify.bonusbar.bar:SetValue(0.5)
    fNotify.bonusbar:SetScript("OnEnter", bonus_OnEnter)
    fNotify.bonusbar:SetScript("OnLeave", GameTooltip_Hide)
    fNotify.compass:SetScript("OnShow", NewQuestAnimation)

    local fBoss = CreateFrame("Frame", "GwQuesttrackerContainerBossFrames", fTracker, "GwQuesttrackerContainer")
    local fScen = CreateFrame("Frame", "GwQuesttrackerContainerScenario", fTracker, "GwQuesttrackerContainer")
    local fAchv = CreateFrame("Frame", "GwQuesttrackerContainerAchievement", fTracker, "GwQuesttrackerContainer")
    local fQuest = CreateFrame("Frame", "GwQuesttrackerContainerQuests", fScroll, "GwQuesttrackerContainer")
    local fBonus = CreateFrame("Frame", "GwQuesttrackerContainerBonusObjectives", fScroll, "GwQuesttrackerContainer")
    fAchv:SetParent(fScroll)
    fQuest:SetParent(fScroll)
    fBonus:SetParent(fScroll)

    if GetSetting("MINIMAP_ENABLED") then
        fTracker:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT")
        fTracker:SetPoint("BOTTOMRIGHT", Minimap, "TOPRIGHT")
    else
        fTracker:SetPoint("TOPRIGHT", Minimap, "BOTTOMRIGHT")
        fTracker:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT")
    end

    fNotify:SetPoint("TOPRIGHT", fTracker, "TOPRIGHT")
    fBoss:SetPoint("TOPRIGHT", fNotify, "BOTTOMRIGHT")
    fScen:SetPoint("TOPRIGHT", fBoss, "BOTTOMRIGHT")

    fTraScr:SetPoint("TOPRIGHT", fScen, "BOTTOMRIGHT")
    fTraScr:SetPoint("BOTTOMRIGHT", fTracker, "BOTTOMRIGHT")

    fScroll:SetPoint("TOPRIGHT", fTraScr, "TOPRIGHT")
    fAchv:SetPoint("TOPRIGHT", fScroll, "TOPRIGHT")
    fQuest:SetPoint("TOPRIGHT", fAchv, "BOTTOMRIGHT")
    fBonus:SetPoint("TOPRIGHT", fQuest, "BOTTOMRIGHT")

    fScroll:SetSize(400, 2)
    fTraScr:SetScrollChild(fScroll)

    fQuest:SetScript("OnEvent", tracker_OnEvent)
    fQuest:RegisterEvent("QUEST_LOG_UPDATE")
    fQuest:RegisterEvent("QUEST_ITEM_UPDATE")
    fQuest:RegisterEvent("QUEST_REMOVED")
    fQuest:RegisterEvent("QUESTLINE_UPDATE")
    fQuest:RegisterEvent("TASK_PROGRESS_UPDATE")
    fQuest:RegisterEvent("QUEST_WATCH_LIST_CHANGED")
    fQuest:RegisterEvent("QUEST_AUTOCOMPLETE")
    fQuest:RegisterEvent("QUEST_ACCEPTED")
    fQuest:RegisterEvent("QUEST_GREETING")
    fQuest:RegisterEvent("QUEST_DETAIL")
    fQuest:RegisterEvent("QUEST_PROGRESS")
    fQuest:RegisterEvent("QUEST_COMPLETE")
    fQuest:RegisterEvent("QUEST_FINISHED")
    fQuest:RegisterEvent("QUEST_POI_UPDATE")
    fQuest:RegisterEvent("PLAYER_MONEY")
    fQuest:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED")

    local header = CreateFrame("Button", "GwQuestHeader", fQuest, "GwQuestTrackerHeader")
    header.icon:SetTexCoord(0, 1, 0.25, 0.5)
    header.title:SetFont(UNIT_NAME_FONT, 14)
    header.title:SetShadowOffset(1, -1)
    header.title:SetText(GwLocalization["TRACKER_QUEST_TITLE"])

    header:SetScript(
        "OnClick",
        function(self)
            local p = self:GetParent()
            if p.collapsed == nil or p.collapsed == false then
                p.collapsed = true
                PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF)
            else
                p.collapsed = false
                PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON)
            end
            updateQuestLogLayout("COLLAPSE")
        end
    )
    header.title:SetTextColor(
        TRACKER_TYPE_COLOR["QUEST"].r,
        TRACKER_TYPE_COLOR["QUEST"].g,
        TRACKER_TYPE_COLOR["QUEST"].b
    )

    loadQuestButtons()
    updateQuestLogLayout("LOAD")

    GW.LoadBossFrame()
    GW.LoadScenarioFrame()
    GW.LoadAchievementFrame()
    GW.LoadBonusFrame()

    fNotify.shouldDisplay = false
    fTracker.trot = GetTime() + 2
	fTracker:SetScript("OnEvent", trackerNotification_OnEvent)
	fTracker:RegisterEvent("PLAYER_ENTERING_WORLD")
	fTracker:RegisterEvent("ZONE_CHANGED_NEW_AREA")
    fTracker:SetScript("OnUpdate", tracker_OnUpdate)
end
GW.LoadQuestTracker = LoadQuestTracker
