Quantcast
--[[-------------------------------------------------------------------
--  TomTomLite - Copyright 2010 - James N. Whitehead II
-------------------------------------------------------------------]]--

local addonName, addon = ...
local L = addon.L

addon.callbacks = LibStub("CallbackHandler-1.0"):New(addon)
addon.mapdata = LibStub("LibMapData-1.0")
addon.libwindow = LibStub("LibWindow-1.1")
addon.waypoints = {}

function addon:Initialize()
    self.db = LibStub("AceDB-3.0"):New("TomTomLiteDB", self.defaults)

    self.arrow = self:CreateCrazyArrow("TomTomLiteArrow")
    self.arrow:SetPoint("CENTER", 0, 0)
    self.arrow:Hide()

    self:RegisterEvent("QUEST_POI_UPDATE")
    self:RegisterEvent("QUEST_LOG_UPDATE")
    self:RegisterMessage("TOMTOMLITE_WAYPOINT_ADDED")
    hooksecurefunc("WatchFrame_Update", function(self)
        addon:UpdateQuestObjectives()
    end)
end

function addon:CreateCrazyArrow(name, parent)
    parent = parent or UIParent
    local frame = CreateFrame("Button", name, parent)

    frame:SetSize(128, 128)
    frame.arrow = frame:CreateTexture("OVERLAY")
    frame.arrow:SetAllPoints()
    frame.arrow:SetTexture("Interface\\Addons\\TomTomLite\\images\\arrow-grey")

    frame.title = frame:CreateFontString("OVERLAY", name .. "Title", "GameFontHighlight")
    frame.info = frame:CreateFontString("OVERLAY", name .. "Info", "GameFontHighlight")
    frame.subtitle = frame:CreateFontString("OVERLAY", name .. "Subtitle", "GameFontHighlight")

    frame.title:SetPoint("TOP", frame, "BOTTOM", 0, 0)
    frame.info:SetPoint("TOP", frame.title, "BOTTOM", 0, 0)
    frame.subtitle:SetPoint("TOP", frame.info, "BOTTOM", 0, 0)

    frame:Hide()

    local PI2 = math.pi * 2

    -- Set up the OnUpdate handler
    frame:SetScript("OnUpdate", function(self, elapsed)
        -- Get the current location
        local cmap = GetCurrentMapAreaID()
        local cx, cy = GetPlayerMapPosition("player")
        local map, floor, x, y = unpack(self.waypoint)
        if not (cmap and cx and cy and map and floor and x and y) then
            -- This shouldn't happen, but bail out in this case
            return
        end

        local distance, xd, yd = addon.mapdata:DistanceWithinContinent(cmap, 0, cx, cy, map, floor, x, y)

        local angle = math.atan2(xd, yd)
        if angle > 0 then
            angle = PI2 - angle
        else
            angle = -angle
        end

        local facing = GetPlayerFacing()
        local faceangle = angle - facing

        local perc = math.abs((math.pi - math.abs(faceangle)) / math.pi)
        local gr,gg,gb = unpack(addon.db.profile.goodcolor)
        local mr,mg,mb = unpack(addon.db.profile.middlecolor)
        local br,bg,bb = unpack(addon.db.profile.badcolor)
        local r,g,b = addon:ColorGradient(perc, br, bg, bb, mr, mg, mb, gr, gg, gb)

        self.arrow:SetVertexColor(r,g,b)
        self.arrow:SetRotation(faceangle)

        self.subtitle:SetFormattedText("%.1f yards", distance)
    end)

    self.libwindow.RegisterConfig(frame, self.db.profile.positions)
    self.libwindow.RestorePosition(frame)
    self.libwindow.MakeDraggable(frame)
    self.libwindow.EnableMouseOnAlt(frame)
    self.libwindow.EnableMouseWheelScaling(frame)

    return frame
end

function addon:AddWaypoint(map, floor, x, y, opt)
    assert(type(map) == "number")
    assert(type(floor) == "number")
    assert(type(x) == "number")
    assert(type(y) == "number")

    local waypoint = {map, floor, x, y}
    if type(opt) == "table" then
        for k, v in pairs(opt) do
            if type(k) ~= "number" then
                waypoint[k] = v
            end
        end
    end

    table.insert(self.waypoints, waypoint)
    self:FireMessage("TOMTOMLITE_WAYPOINT_ADDED", waypoint)
end

function addon:TOMTOMLITE_WAYPOINT_ADDED(msg, waypoint, ...)
    local zone, floor, x, y = unpack(waypoint)
    local lzone = self.mapdata:MapLocalize(zone)
    --self:Printf("Added a waypoint at (%.2f, %.2f) in %s", x * 100, y * 100, lzone)

    self.arrow.waypoint = waypoint
    self.arrow.title:SetText(waypoint.title or L["Unknown waypoint"])
    self.arrow.info:SetFormattedText("%.2f, %.2f - %s", x * 100, y * 100, lzone)
    self.arrow:Show()
end

local function POIAnchorToCoord(poiframe)
    local point, relto, relpoint, x, y = poiframe:GetPoint()
    local frame = WorldMapDetailFrame
    local width = frame:GetWidth()
    local height = frame:GetHeight()
    local scale = frame:GetScale() / poiframe:GetScale()
    local cx = (x / scale) / width
    local cy = (-y / scale) / height

    if cx < 0 or cx > 1 or cy < 0 or cy > 1 then
        return nil, nil
    end

    local map, floor = GetCurrentMapAreaID()
    return map, floor or 0, cx, cy
end

local function findQuestFrameFromQuestIndex(index)
    -- Try to find the correct quest frame
    for i = 1, MAX_NUM_QUESTS do
        local questFrame = _G["WorldMapQuestFrame" .. i];
        if not questFrame then
            break
        elseif questFrame.questLogIndex == index then
            return questFrame
        end
    end
end

function addon:QUEST_POI_UPDATE()
    self:UpdateQuestObjectives()
end

function addon:QUEST_LOG_UPDATE()
    self:UpdateQuestObjectives()
end

function addon:UpdateQuestObjectives()
    -- Only do an objective scan if the option is enabled
    if not self.db.profile.trackQuestObjectives then
        return
    end

    QuestPOIUpdateIcons()

    local watchIndex = 1
    while true do
        -- Get the first quest item in the watch frame
        local questIndex = GetQuestIndexForWatch(watchIndex)
        if not questIndex then
            self.arrow:Hide()
            return
        end

        local title = GetQuestLogTitle(questIndex)
        local qid = select(9, GetQuestLogTitle(questIndex))

        local completed, x, y, objective = QuestPOIGetIconInfo(qid)

        -- Check to see if there was coordinate information for the current point
        if x and y then
            local map, floor = GetCurrentMapAreaID()

            if not floor then floor = 0 end
            if completed then
                title = "Turn in: " .. title
            end

            if x and y and map and floor then
                self:AddWaypoint(map, floor, x, y, {title = title})
            end
            return
        end

        watchIndex = watchIndex + 1
    end
end