Revision 370 (by barfolomeu, 2011/12/10 01:49:26) Fix bug where old variable name was still in use.
--[[

Copyright 2008-∞ Daniel Ceregatti (daniel@ceregatti.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

Some code borrowed from other addons, namely:

TomTom
FuBar_SpeedFu
HandyNotes
Omen

And surely others that I can't remember at the moment. Most, if not all,
are GPL or all rights reserved, but I've obtained permission to copy.

I would also like to thank the many people in #wowace on Freenode that have
been helpful while I've worked on this addon:

ckknight
jnwhiteh
Shefki
Xinhuan

]]--

--@debug@
local INFO = 1
local WARN = 2
local DEBUG1 = 4
local DEBUG2 = 8
local levels = {
  [1] = "  INFO",
  [2] = "  WARN",
  [4] = "DEBUG1",
  [8] = "DEBUG2",
}
--@end-debug@

-- Need to version the db in case of changes
local DBVERSION = 1

-- Locale variable
local L = LibStub("AceLocale-3.0"):GetLocale("FlightHUD", false)

-- Astrolabe for waypoints and horizontal speed
local Astrolabe = DongleStub("Astrolabe-1.0")

-- For the copy/paste edit box for bug reports
local AceGUI = LibStub("AceGUI-3.0")

-- Keybindings
BINDING_HEADER_FLIGHTHUD = "FlightHUD"
BINDING_NAME_FLIGHTHUD_TOGGLE = L["Toggle FlightHUD"]
BINDING_NAME_FLIGHTHUD_TOGGLECONTINENT = L["Toggle continenet-wide waypoints"]

-- Sizes, ratios, and offsets
local MainFrameWidth = 512
local MainFrameHeight = 256
local MainFrameWidthDiv = MainFrameWidth / 2
local MainFrameHeightDiv = MainFrameHeight / 2

local MainFrameWidthLess = MainFrameWidthDiv - 32
local MainFrameHeightLess = MainFrameHeightDiv - 32

local fov = 90 -- 90 degree field of view
local bxscale = MainFrameWidthDiv / (fov / 2) -- 5.688 = (512 / 2) / (90 / 2)
local byscale = MainFrameHeight / fov -- 2.844 = 256/90
local yardsdiv = 100 / 7

local headingOffset = .268
local PitchFactor = 1.1575

-- Some math
local math_sqrt = math.sqrt
local math_floor = math.floor
local math_pi = math.pi
local math_abs = math.abs
local math_cos = math.cos
local math_sin = math.sin
local math_deg = math.deg
local math_rad = math.rad
local rad90 = math_rad (90)

-- Local variables
local OnUpdateElapsed = 0
local EventCheckOnUpdateElapsed = 0
local SpeedFrequency = 0.5 -- Make this configurable
local ForceToggle = 0
local ForceContinentToggle = false
local oldWorldMapScript
local CurrentQuest = -1
local lastSound = 0
local AlreadyInObjectivesChanged = false
local playerName, _ = UnitName("player")

local recursionCheck = {}

local info = {}
local zoneinfo = {}
local waypointinfo = {}
local zonedisplayoptions = {
  [1] = L["Show in continent"],
  [2] = L["Show in zone"],
  [3] = L["Continent, but not zone"],
}
local waypointdisplayoptions = {
  [1] = L["Show everything"],
  [2] = L["Show only distance and heading"],
  [3] = L["Show only ETA"],
  [4] = L["Show nothing"],
}
local icons = {
  [1] = UnitPopupButtons.RAID_TARGET_1, -- Star
  [2] = UnitPopupButtons.RAID_TARGET_2, -- Circle
  [3] = UnitPopupButtons.RAID_TARGET_3, -- Diamond
  [4] = UnitPopupButtons.RAID_TARGET_4, -- Triangle
  [5] = UnitPopupButtons.RAID_TARGET_5, -- Moon
  [6] = UnitPopupButtons.RAID_TARGET_6, -- Square
  [7] = UnitPopupButtons.RAID_TARGET_7, -- Cross
  [8] = UnitPopupButtons.RAID_TARGET_8, -- Skull
  [9] = {text = MINIMAP_TRACKING_AUCTIONEER, icon = "Interface\\Minimap\\Tracking\\Auctioneer"},
  [10] = {text = MINIMAP_TRACKING_BANKER, icon = "Interface\\Minimap\\Tracking\\Banker"},
  [11] = {text = MINIMAP_TRACKING_BATTLEMASTER, icon = "Interface\\Minimap\\Tracking\\BattleMaster"},
  [12] = {text = MINIMAP_TRACKING_FLIGHTMASTER, icon = "Interface\\Minimap\\Tracking\\FlightMaster"},
  [13] = {text = MINIMAP_TRACKING_INNKEEPER, icon = "Interface\\Minimap\\Tracking\\Innkeeper"},
  [14] = {text = MINIMAP_TRACKING_MAILBOX, icon = "Interface\\Minimap\\Tracking\\Mailbox"},
  [15] = {text = MINIMAP_TRACKING_REPAIR, icon = "Interface\\Minimap\\Tracking\\Repair"},
  [16] = {text = MINIMAP_TRACKING_STABLEMASTER, icon = "Interface\\Minimap\\Tracking\\StableMaster"},
  [17] = {text = MINIMAP_TRACKING_TRAINER_CLASS, icon = "Interface\\Minimap\\Tracking\\Class"},
  [18] = {text = MINIMAP_TRACKING_TRAINER_PROFESSION, icon = "Interface\\Minimap\\Tracking\\Profession"},
  [19] = {text = MINIMAP_TRACKING_TRIVIAL_QUESTS, icon = "Interface\\Minimap\\Tracking\\TrivialQuests"},
  [20] = {text = MINIMAP_TRACKING_VENDOR_AMMO, icon = "Interface\\Minimap\\Tracking\\Ammunition"},
  [21] = {text = MINIMAP_TRACKING_VENDOR_FOOD, icon = "Interface\\Minimap\\Tracking\\Food"},
  [22] = {text = MINIMAP_TRACKING_VENDOR_POISON, icon = "Interface\\Minimap\\Tracking\\Poisons"},
  [23] = {text = MINIMAP_TRACKING_VENDOR_REAGENT, icon = "Interface\\Minimap\\Tracking\\Reagents"},
  [24] = {text = FACTION_ALLIANCE, icon = "Interface\\TargetingFrame\\UI-PVP-Alliance", tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
  [25] = {text = FACTION_HORDE, icon = "Interface\\TargetingFrame\\UI-PVP-Horde", tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
  [26] = {text = FACTION_STANDING_LABEL4, icon = "Interface\\TargetingFrame\\UI-PVP-FFA", tCoordLeft = 0.05, tCoordRight = 0.65, tCoordTop = 0, tCoordBottom = 0.6},
  [27] = {text = ARENA, icon = "Interface\\PVPFrame\\PVP-ArenaPoints-Icon"},
  [28] = {text = L["Portal"], icon = "Interface\\Icons\\Spell_Arcane_PortalDalaran"},
  [29] = {text = L["Quest Available"], icon = "Interface\\Minimap\\Tracking\\ObjectIcons", tCoordLeft = 0.125, tCoordRight = 0.25, tCoordTop = 0.5, tCoordBottom = 1 },
  [30] = {text = L["Quest Complete"], icon = "Interface\\Minimap\\Tracking\\ObjectIcons", tCoordLeft = 0.25, tCoordRight = 0.375, tCoordTop = 0.5, tCoordBottom = 1 },
}

 -- "defines"
local SHOW_IN_CONTINENT = 1
local SHOW_IN_ZONE = 2
local CONTINENT_NOT_ZONE = 3

local SHOW_EVERYTHING = 1
local SHOW_DISTANCE_HEADING = 2
local SHOW_ETA = 3
local SHOW_NOTHING = 4

-- Local aliases for supposed expensive table lookups
local GetUnitSpeed = GetUnitSpeed
local GetUnitPitch = GetUnitPitch

-- All local functions
local function round (num, places)
  local num = num or 0 -- In case num is nil?
  local mult = 10^(places or 0)
  return math_floor (num * mult + 0.5) / mult
end

local function GetCurrentCursorPosition()
  local x, y = GetCursorPosition()
  local left, top = WorldMapDetailFrame:GetLeft(), WorldMapDetailFrame:GetTop()
  local width = WorldMapDetailFrame:GetWidth()
  local height = WorldMapDetailFrame:GetHeight()
  local scale = WorldMapDetailFrame:GetEffectiveScale()
  local cx = (x/scale - left) / width
  local cy = (top - y/scale) / height
  if cx < 0 or cx > 1 or cy < 0 or cy > 1 then
    return nil, nil
  end
  return cx, cy
end

local function GetHorizontalSpeed (map, lfloor, x, y, arg)
  -- Horizontal speed text, code borrowed from FuBar_SpeedFu
  FlightHUD.vars.Elapsed = FlightHUD.vars.Elapsed + arg;
  if (FlightHUD.vars.Elapsed > SpeedFrequency) then
    if not FlightHUD.vars.lastPos then
      if map and x and y then
        FlightHUD.vars.lastTime = GetTime()
        FlightHUD.vars.lastPos = { map = map, floor = lfloor, x = x, y = y }
      else
        return 0
      end
    end

    local CurrTime = GetTime()

    local dist = Astrolabe:ComputeDistance(
      FlightHUD.vars.lastPos.map,
      FlightHUD.vars.lastPos.floor,
      FlightHUD.vars.lastPos.x,
      FlightHUD.vars.lastPos.y, map, lfloor, x, y) or 0
    local delta = CurrTime - FlightHUD.vars.lastTime

    if dist > 0 then
      FlightHUD.vars.speed = floor ((dist / delta / 7 * 100)) + 0.497
    else
      FlightHUD.vars.speed = 0
    end
    FlightHUD.vars.lastTime = CurrTime
    FlightHUD.vars.lastPos.map = map
    FlightHUD.vars.lastPos.floor = lfloor
    FlightHUD.vars.lastPos.x = x
    FlightHUD.vars.lastPos.y = y
    FlightHUD.vars.Elapsed = 0
  end
  return FlightHUD.vars.speed
end

local function FindWaypointFrame (visible)
  -- Search the pool for an unused frame
  for frameid, waypointframe in pairs (FlightHUD.waypointframes) do
    if not waypointframe.inuse then
      waypointframe.visible = visible
      waypointframe.inuse = true
      return frameid
    end
  end
  -- None were found. Create a new one
  local frame = {}
  frame.inuse = true
  frame.visible = visible
  local frameid = #FlightHUD.waypointframes + 1

  if not FlightHUDMapOverlay then
    local overlay = CreateFrame("Frame", "FlightHUDMapOverlay", WorldMapButton)
    overlay:SetAllPoints(true)
  end

  -- Minimap frame
  frame.minimap = CreateFrame("Button", nil, Minimap)
  frame.minimap:SetHeight(12)
  frame.minimap:SetWidth(12)
  frame.minimap:RegisterForClicks("RightButtonUp")
  frame.minimap.frame = frame
  -- Minimap icon
  frame.minimap.icon = frame.minimap:CreateTexture("BACKGROUND")
  -- Worldmap frame
  frame.worldmap = CreateFrame("Button", nil, FlightHUDMapOverlay)
  frame.worldmap:SetHeight(12)
  frame.worldmap:SetWidth(12)
  frame.worldmap:RegisterForClicks("RightButtonUp")
  frame.worldmap.frame = frame
  -- Worldmap icon
  frame.worldmap.icon = frame.worldmap:CreateTexture("ARTWORK")
  -- Waypoint graphic
  frame.WaypointFrame = CreateFrame("Frame", "WaypointFrame", FlightHUD.FlightHUDFrame)
  frame.WaypointFrame:Hide()
  frame.WaypointFrame:SetScale(FlightHUD.db.profile.FrameScale)
  frame.WaypointFrame:SetWidth(16)
  frame.WaypointFrame:SetHeight(16)
  frame.WaypointFrame:SetPoint("CENTER", "FlightHUDFrame", "CENTER", 0, 0)
  -- Raid UI graphic
  frame.icon = frame.WaypointFrame:CreateTexture(nil, "OVERLAY")
  frame.icon:Show()
  frame.icon:SetBlendMode("BLEND")
  frame.icon:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  frame.icon:SetWidth(16)
  frame.icon:SetHeight(16)
  frame.icon:SetPoint("TOP", frame.WaypointFrame)
  -- Waypoint text
  frame.TitleText = frame.WaypointFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  frame.TitleText:Show()
  frame.TitleText:SetWidth(1000)
  frame.TitleText:SetHeight(300)
  frame.TitleText:SetJustifyV("TOP")
  frame.TitleText:SetPoint("TOP", frame.icon, "TOP", 0, -17)
  frame.TitleText:SetTextColor(unpack(FlightHUD.db.profile.WaypointTextColor))
  frame.TitleText:SetShadowColor (unpack(FlightHUD.db.profile.WaypointTextShadowColor))
  frame.TitleText:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  frame.TitleText:SetFont(FlightHUD.HeadingText:GetFont(), FlightHUD.db.profile.FontScale)
  -- Add it to the frame pool
  FlightHUD.waypointframes[frameid] = frame
  return frameid
end

local function strip_colors(x)
  local ass = (x:gsub("|r", ""):gsub("|c%x%x%x%x%x%x%x%x", ""))
  return ass
end

local function MakeWaypointID (data)
  return format ("%d-%d-%f-%f", data.map, data.floor, data.x, data.y)
end

local function AssignWaypointToFrame (waypointid, waypoint)
  --@debug@
  FlightHUD:Debug(DEBUG1, "AssignWaypointToFrame")
  --@end-debug@
  local frameid = FindWaypointFrame (FlightHUD:ShouldShowWaypoint(waypoint))
  local waypoint = FlightHUD.db.profile.waypoints[waypointid]
  local waypointframe = FlightHUD.waypointframes[frameid]
  local t = icons[waypoint.icon]
  waypointframe.waypoint = waypoint

  waypointframe.minimap.icon:SetAllPoints()
  waypointframe.minimap.icon:SetTexture(t.icon)

  waypointframe.worldmap.icon:SetAllPoints()
  waypointframe.worldmap.icon:SetTexture(t.icon)

  waypointframe.icon:SetAllPoints()
  waypointframe.icon:SetTexture(t.icon)

  if waypoint.icon >= 1 and waypoint.icon <= 8 then
    SetRaidTargetIconTexture (waypointframe.icon, waypoint.icon)
    SetRaidTargetIconTexture (waypointframe.minimap.icon, waypoint.icon)
    SetRaidTargetIconTexture (waypointframe.worldmap.icon, waypoint.icon)
  end

  if t.tCoordLeft then
    waypointframe.minimap.icon:SetTexCoord(t.tCoordLeft, t.tCoordRight, t.tCoordTop, t.tCoordBottom)
    waypointframe.worldmap.icon:SetTexCoord(t.tCoordLeft, t.tCoordRight, t.tCoordTop, t.tCoordBottom)
    waypointframe.icon:SetTexCoord(t.tCoordLeft, t.tCoordRight, t.tCoordTop, t.tCoordBottom)
  end

  waypointframe.TitleText:SetText(waypoint.title)
  return frameid
end

local function AddWaypoint (data)
  --@debug@
  FlightHUD:Debug(DEBUG1, "AddWaypoint")
  --@end-debug@
  local waypointid = MakeWaypointID (data)
  data.dbversion = DBVERSION
  data.waypointid = waypointid
  data.playerName = data.playerName or playerName
  data.titlebg = strip_colors (data.title)
  FlightHUD.db.profile.waypoints[waypointid] = data
  local frameid = AssignWaypointToFrame (waypointid, data)
  FlightHUD.db.profile.waypoints[waypointid].frameid = frameid
  data.frameid = frameid
  local waypointframe = FlightHUD.waypointframes[frameid]
  Astrolabe:PlaceIconOnWorldMap (
    FlightHUDMapOverlay,
    waypointframe.worldmap,
    data.map,
    data.floor,
    data.x,
    data.y
  )
  Astrolabe:PlaceIconOnMinimap (
    waypointframe.minimap,
    data.map,
    data.floor,
    data.x,
    data.y
  )
  FlightHUD:ShouldShowMinimap (data)
  FlightHUD:ShouldShowWorldmap (data)
  --@debug@
  FlightHUD:Debug(DEBUG1, "AddWaypoint", format ("  frameid: %d", frameid))
  --@end-debug@
  return frameid
end

local click_verify = {
  ["A"] = function() return IsAltKeyDown() end,
  ["C"] = function() return IsControlKeyDown() end,
  ["S"] = function() return IsShiftKeyDown() end,
}

local ModifierValues = {
  ["A"] = L["Alt"],
  ["C"] = L["Ctrl"],
  ["S"] = L["Shift"],
  ["AC"] = L["Alt-Ctrl"],
  ["AS"] = L["Alt-Shift"],
  ["CS"] = L["Ctrl-Shift"],
  ["ACS"] = L["Alt-Ctrl-Shift"],
}

local orig_WorldMapButton_OnClick = WorldMapButton_OnClick

WorldMapButton_OnClick = function(self, ...)
  local mouseButton, button = ...
  if mouseButton == "RightButton" then
    -- Check for all the modifiers that are currently set
    for mod in FlightHUD.db.profile.WorldmapModifier:gmatch("[ACS]") do
      if not click_verify[mod] or not click_verify[mod]() then
        return orig_WorldMapButton_OnClick and orig_WorldMapButton_OnClick(self, ...) or true
      end
    end
    -- Actually try to add a note
    FlightHUD.EditFrame.map, FlightHUD.EditFrame.floor = GetCurrentMapAreaID(), GetCurrentMapDungeonLevel()
    FlightHUD.EditFrame.x, FlightHUD.EditFrame.y = GetCurrentCursorPosition ()
	FlightHUD.EditFrame.continent = GetCurrentMapContinent()
    local dx = FlightHUD.EditFrame.x * 100
    local dy = FlightHUD.EditFrame.y * 100
--    if FlightHUD.EditFrame.z == 0 then
--      return orig_WorldMapButton_OnClick and orig_WorldMapButton_OnClick(self, ...) or true
--    end
    FlightHUD.EditFrame:Hide()
    FlightHUD.EditFrame:Show()
  else
    return orig_WorldMapButton_OnClick and orig_WorldMapButton_OnClick(self, ...) or true
  end
end

-- Add our localized text to the map help text
local origMapText

local orig_WorldMapButton_OnShow = WorldMapButton_OnShow

WorldMapButton_OnShow = function(self, ...)
  origMapText = WorldMapMagnifyingGlassButton:GetText()
  WorldMapMagnifyingGlassButton:SetText (origMapText .. "\n" ..
    ModifierValues[FlightHUD.db.profile.WorldmapModifier] .. L["+"] .. L["Right Click To Add a FlightHUD Waypoint"])
end

local orig_WorldMapButton_OnHide = WorldMapButton_OnHide

WorldMapButton_OnHide = function(self, ...)
  WorldMapMagnifyingGlassButton:SetText(origMapText)
end

FlightHUD = LibStub("AceAddon-3.0"):NewAddon("FlightHUD", "AceConsole-3.0", "AceEvent-3.0")

function FlightHUD:OnInitialize()
  self.enabled = false
  self.vars = {}
  self.vars.lastTime = 0
  self.vars.speed = 0
  self.vars.Elapsed = 0
  self.waypointframes = {}
  self.ShowCompassGraphic = false
  self.ShowPitchImage = false
  self.mounted = false
  self.LastMounted = false
  self.swimming = false
  self.LastSwimming = false
  self.flying = false
  self.LastFlying = false
  self.IsShowing = false
  self.CBid = {}
  self.deletewaypoint = nil
  -- Here so I can manipulate the value in-game
  self.PitchFactor = PitchFactor
  self.DisplayErrors = true
  self.ErrorShowing = false
  self.SavedErrors = {}

  StaticPopupDialogs["FLIGHTHUD_CONFIRM_WAYPOINT_DELETE"] = {
    text = L["Really delete waypoint '%s'?"],
    button1 = L["Yes"],
    button2 = L["Cancel"],
    OnAccept = function()
      FlightHUD:RemoveWaypoint (nil, true)
    end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
  }

  StaticPopupDialogs["FLIGHTHUD_CONFIRM_DBVERSION"] = {
    text = L["Some of your saved waypoints use an obsolete format.\nThese waypoints have been purged.\nSorry :("],
    button2 = L["OK"],
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
  }

  StaticPopupDialogs["FLIGHTHUD_ERROR_DETECTED"] = {
    text = L["FlightHUD has detected an error condition. Please post a bug with the following attached:\n\n%s"],
    button2 = L["OK"],
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
  }

  self.db = LibStub("AceDB-3.0"):New("FlightHUDDB", FlightHUDDefaultConfigDB, "Default")
  self.db.RegisterCallback(self, "OnDatabaseShutdown", "DatabaseShutdown")

  LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("FlightHUD", FlightHUDConfig)

  self.optionsFrames = {}
  local ACD3 = LibStub("AceConfigDialog-3.0")
  self.optionsFrames.FlightHUD = LibStub("LibAboutPanel").new (nil, "FlightHUD")

  -- Thanks, Omen!
  self.optionsFrames.ShowEvents = ACD3:AddToBlizOptions("FlightHUD", L["General"], "FlightHUD", "General")
  self.optionsFrames.ShowEvents = ACD3:AddToBlizOptions("FlightHUD", L["Show Events"], "FlightHUD", "ShowEvents")
  self.optionsFrames.SpeedVars = ACD3:AddToBlizOptions("FlightHUD", L["Speed Controls"], "FlightHUD", "SpeedVars")
  self.optionsFrames.Scaling = ACD3:AddToBlizOptions("FlightHUD", L["Scaling"], "FlightHUD", "Scaling")
  self.optionsFrames.TextOptions = ACD3:AddToBlizOptions("FlightHUD", L["Text Options"], "FlightHUD", "TextOptions")
  self.optionsFrames.ColorOptions = ACD3:AddToBlizOptions("FlightHUD", L["Color Options"], "FlightHUD", "ColorOptions")
  self.optionsFrames.WaypointOptions = ACD3:AddToBlizOptions("FlightHUD", L["Waypoint Options"], "FlightHUD", "WaypointOptions")
  self.optionsFrames.ResetOptions = ACD3:AddToBlizOptions("FlightHUD", L["Reset"], "FlightHUD", "ResetOptions")
  --@debug@
  self.optionsFrames.ResetOptions = ACD3:AddToBlizOptions("FlightHUD", L["Debug"], "FlightHUD", "DebugOptions")
  --@end-debug@

  self:RegisterChatCommand("flighthud", function()
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.ResetOptions)
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.FlightHUD)
  end)
  self:RegisterChatCommand("fh", function()
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.ResetOptions)
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.FlightHUD)
  end)
  self:RegisterChatCommand("fht", function()
    FlightHUD.db.profile.DisableAddon = not FlightHUD.db.profile.DisableAddon
    FlightHUD.EnableAddon ()
  end)

  -- EventCheck frame to monitor if we're swimming
  self.EventCheckFrame = CreateFrame("Frame", "FlightHUDEventCheckFrame", UIParent)
  self.EventCheckFrame:SetPoint("CENTER")
  self.EventCheckFrame:SetWidth(32)
  self.EventCheckFrame:SetHeight(32)

  -- The parent frame
  self.FlightHUDFrame = CreateFrame("ScrollFrame", "FlightHUDFrame", UIParent)
  self.FlightHUDFrame:Hide()
  self.FlightHUDFrame:SetScale(self.db.profile.FrameScale)
  if (self.db.profile.FramePoint_point ~= false) then
    local scale = self.FlightHUDFrame:GetScale()
    local x = self.db.profile.FramePoint_xOfs / scale
    local y = self.db.profile.FramePoint_yOfs / scale
    self.FlightHUDFrame:SetPoint(
     self.db.profile.FramePoint_point,
      UIParent,
      self.db.profile.FramePoint_relativePoint,
      x,
      self.db.profile.FramePoint_yOfs
    )
  else
    self.FlightHUDFrame:SetPoint("CENTER")
  end
  self.FlightHUDFrame:SetWidth(MainFrameWidth)
  self.FlightHUDFrame:SetHeight(MainFrameHeight)
  -- HUD background image (always shown)
  self.timage = self.FlightHUDFrame:CreateTexture(nil, "BACKGROUND")
  self.timage:Show()
  self.timage:SetBlendMode("BLEND")
  self.timage:SetTexture("Interface\\AddOns\\FlightHUD\\transparent")
  self.timage:SetAlpha(self.db.profile.HUDBGAlpha)
  self.timage:SetWidth(512)
  self.timage:SetHeight(256)
  self.timage:SetPoint("CENTER", self.FlightHUDFrame)
  -- Heading text
  self.HeadingText = self.FlightHUDFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  if (FlightHUD.db.profile.ShowHeadingText) then
    self.HeadingText:Show()
  else
    self.HeadingText:Hide()
  end
  self.HeadingText:SetWidth(512)
  self.HeadingText:SetHeight(16)
  self.HeadingText:SetTextColor(unpack (self.db.profile.HeadingTextColor))
  self.HeadingText:SetPoint("CENTER", self.FlightHUDFrame)
  self.HeadingText:SetJustifyV("TOP")
  self.HeadingText:SetJustifyH("RIGHT")
  self.HeadingText:SetAlpha(self.db.profile.HUDAlpha)
  self.HeadingText:SetFont(self.HeadingText:GetFont(), self.db.profile.FontScale)
  -- Pitch text
  self.PitchText = self.FlightHUDFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  if (self.db.profile.ShowPitchText) then
    self.PitchText:Show()
  else
    self.PitchText:Hide()
  end
  self.PitchText:SetWidth(512)
  self.PitchText:SetHeight(16)
  self.PitchText:SetTextColor(unpack (self.db.profile.PitchTextColor))
  self.PitchText:SetPoint("CENTER", self.FlightHUDFrame)
  self.PitchText:SetJustifyV("TOP")
  self.PitchText:SetJustifyH("LEFT")
  self.PitchText:SetAlpha(self.db.profile.HUDAlpha)
  self.PitchText:SetFont(self.PitchText:GetFont(), self.db.profile.FontScale)
  -- Coordinates text
  self.CoordinatesText = self.FlightHUDFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  if (self.db.profile.ShowCoordinatesText) then
    self.CoordinatesText:Show()
  else
    self.CoordinatesText:Hide()
  end
  self.CoordinatesText:SetWidth(512)
  self.CoordinatesText:SetHeight(16)
  self.CoordinatesText:SetTextColor(unpack (self.db.profile.CoordinatesTextColor))
  self.CoordinatesText:SetPoint("TOP", self.FlightHUDFrame)
  self.CoordinatesText:SetJustifyV("TOP")
  self.CoordinatesText:SetJustifyH("LEFT")
  self.CoordinatesText:SetAlpha(self.db.profile.HUDAlpha)
  self.CoordinatesText:SetFont(self.CoordinatesText:GetFont(), self.db.profile.FontScale)
  -- Speed text
  self.SpeedText = self.FlightHUDFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  if (self.db.profile.ShowSpeedText) then
    self.SpeedText:Show()
  else
    self.SpeedText:Hide()
  end
  self.SpeedText:SetWidth(512)
  self.SpeedText:SetHeight(16)
  self.SpeedText:SetTextColor(unpack (self.db.profile.SpeedTextColor))
  self.SpeedText:SetPoint("TOP", self.FlightHUDFrame)
  self.SpeedText:SetJustifyV("TOP")
  self.SpeedText:SetJustifyH("RIGHT")
  self.SpeedText:SetAlpha(self.db.profile.HUDAlpha)
  self.SpeedText:SetFont(self.SpeedText:GetFont(), self.db.profile.FontScale)
  -- First compass heading image (shown/hidden in the OnUpdate)
  self.CompassHeadingImage1 = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.CompassHeadingImage1:Hide()
  self.CompassHeadingImage1:SetBlendMode("BLEND")
  self.CompassHeadingImage1:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD1")
  self.CompassHeadingImage1:SetVertexColor(unpack(self.db.profile.CompassColor))
  self.CompassHeadingImage1:SetAlpha(self.db.profile.HUDAlpha)
  self.CompassHeadingImage1:SetWidth(512)
  self.CompassHeadingImage1:SetHeight(32)
  self.CompassHeadingImage1:SetPoint("BOTTOM", self.FlightHUDFrame)
  -- Second compass heading image (shown/hidden in the OnUpdate)
  self.CompassHeadingImage2 = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.CompassHeadingImage2:Hide()
  self.CompassHeadingImage2:SetBlendMode("BLEND")
  self.CompassHeadingImage2:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD2")
  self.CompassHeadingImage2:SetVertexColor(unpack(self.db.profile.CompassColor))
  self.CompassHeadingImage2:SetAlpha(self.db.profile.HUDAlpha)
  self.CompassHeadingImage2:SetWidth(512)
  self.CompassHeadingImage2:SetHeight(32)
  self.CompassHeadingImage2:SetPoint("BOTTOM", self.FlightHUDFrame)
  -- Heading center graphic
  self.HeadingCenterImage = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.HeadingCenterImage:SetBlendMode("BLEND")
  self.HeadingCenterImage:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD5")
  self.HeadingCenterImage:SetVertexColor(unpack(self.db.profile.HeadingCenterColor))
  self.HeadingCenterImage:SetAlpha(self.db.profile.HUDAlpha)
  self.HeadingCenterImage:SetWidth(16)
  self.HeadingCenterImage:SetHeight(256)
  self.HeadingCenterImage:SetPoint("CENTER", self.FlightHUDFrame)
  -- Pitch graphic 1
  self.PitchImage1 = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.PitchImage1:SetBlendMode("BLEND")
  self.PitchImage1:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD3")
  self.PitchImage1:SetVertexColor(unpack(self.db.profile.PitchColor))
  self.PitchImage1:SetAlpha(self.db.profile.HUDAlpha)
  self.PitchImage1:SetWidth(512)
  self.PitchImage1:SetHeight(190)
  self.PitchImage1:SetPoint("CENTER", self.FlightHUDFrame)
  -- Pitch graphic 2, for overlap
  self.PitchImage2 = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.PitchImage2:SetBlendMode("BLEND")
  self.PitchImage2:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD3")
  self.PitchImage2:SetVertexColor(unpack(self.db.profile.PitchColor))
  self.PitchImage2:SetAlpha(self.db.profile.HUDAlpha)
  self.PitchImage2:SetWidth(512)
  self.PitchImage2:SetHeight(190)
  self.PitchImage2:SetPoint("CENTER", self.FlightHUDFrame)
  -- Artificial horizon graphic
  self.ArtificialHorizonImage = self.FlightHUDFrame:CreateTexture(nil, "OVERLAY")
  self.ArtificialHorizonImage:SetBlendMode("BLEND")
  self.ArtificialHorizonImage:SetTexture("Interface\\AddOns\\FlightHUD\\FlightHUD4")
  self.ArtificialHorizonImage:SetVertexColor(unpack(self.db.profile.ArtificialHorizonColor))
  self.ArtificialHorizonImage:SetAlpha(self.db.profile.HUDAlpha)
  self.ArtificialHorizonImage:SetWidth(128)
  self.ArtificialHorizonImage:SetHeight(16)
  self.ArtificialHorizonImage:SetPoint("CENTER", self.FlightHUDFrame)
  -- "Add Waypoint" dialog
  -----------------------------------------------------------------------------------
  -- BEGIN -- Code taken mostly verbatim from HandyNotes
  -----------------------------------------------------------------------------------
  local backdrop2 = {
    bgFile = nil,
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 16,
    insets = { left = 0, right = 0, top = 0, bottom = 0 },
  }
  self.EditFrame = CreateFrame("Frame", nil, WorldMapButton)
  self.EditFrame:Hide()
  self.EditFrame:SetWidth(350)
  self.EditFrame:SetHeight(260)
  self.EditFrame:SetPoint("BOTTOM", 0, 90)
  self.EditFrame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
    tile = true, tileSize = 32, edgeSize = 32,
    insets = { left = 11, right = 12, top = 12, bottom = 11 },
  })
  self.EditFrame:SetBackdropColor(0,0,0,1)
  self.EditFrame:EnableMouse(true)
  self.EditFrame:SetToplevel(true)
  self.EditFrame:SetClampedToScreen(true)
  self.EditFrame:SetMovable(true)
  self.EditFrame:SetFrameStrata(WorldMapButton:GetFrameStrata())
  self.EditFrame.titleTexture = self.EditFrame:CreateTexture(nil, "ARTWORK")
  self.EditFrame.titleTexture:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  self.EditFrame.titleTexture:SetWidth(375)
  self.EditFrame.titleTexture:SetHeight(64)
  self.EditFrame.titleTexture:SetPoint("TOP", 0, 12)
  self.EditFrame.titleTexture = temp
  self.EditFrame.title = self.EditFrame:CreateFontString(nil, "ARTWORK", "GameFontNormal")
  self.EditFrame.title:SetPoint("TOP", 0, -3)
  self.EditFrame.title:SetText(L["Set FlightHUD Waypoint"])
  -- This creates a transparent textureless draggable frame to move self.EditFrame
  -- It overlaps the above title text and texture (more or less) exactly.
  temp = CreateFrame("Frame", nil, self.EditFrame)
  temp:SetWidth(150)
  temp:SetHeight(30)
  temp:SetPoint("TOP", 0, 8)
  temp:EnableMouse(true)
  temp:RegisterForDrag("LeftButton")
  temp:SetScript("OnDragStart", function(self)
    self:GetParent():StartMoving()
  end)
  temp:SetScript("OnDragStop", function(self)
    self:GetParent():StopMovingOrSizing()
  end)
  -- Create the Close button
  self.EditFrame.CloseButton = CreateFrame("Button", nil, self.EditFrame, "UIPanelCloseButton")
  self.EditFrame.CloseButton:SetPoint("TOPRIGHT", -2, -1)
  self.EditFrame.CloseButton:SetHitRectInsets(5, 5, 5, 5)
  -- Create and position the Title text string
  self.EditFrame.titletext = self.EditFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
  self.EditFrame.titletext:SetPoint("TOPLEFT", 25, -28)
  self.EditFrame.titletext:SetText(L["Title"])
-- Create the Title Input Box and position it below the text
  self.EditFrame.titleinputframe = CreateFrame("Frame", nil, self.EditFrame)
  self.EditFrame.titleinputframe:SetWidth(300)
  self.EditFrame.titleinputframe:SetHeight(24)
  self.EditFrame.titleinputframe:SetBackdrop(backdrop2)
  self.EditFrame.titleinputframe:SetPoint("TOPLEFT", self.EditFrame.titletext, "BOTTOMLEFT", 0, 0)
  self.EditFrame.titleinputbox = CreateFrame("EditBox", nil, self.EditFrame.titleinputframe)
  self.EditFrame.titleinputbox:SetWidth(290)
  self.EditFrame.titleinputbox:SetHeight(24)
  self.EditFrame.titleinputbox:SetMaxLetters(100)
  self.EditFrame.titleinputbox:SetNumeric(false)
  self.EditFrame.titleinputbox:SetAutoFocus(false)
  self.EditFrame.titleinputbox:SetFontObject("GameFontHighlightSmall")
  self.EditFrame.titleinputbox:SetPoint("TOPLEFT", 5, 1)
  self.EditFrame.titleinputbox:SetScript("OnShow", self.EditFrame.titleinputbox.SetFocus)
  self.EditFrame.titleinputbox:SetScript("OnEscapePressed", self.EditFrame.titleinputbox.ClearFocus)
  -- Create and position the Description text string
  self.EditFrame.desctext = self.EditFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
  self.EditFrame.desctext:SetPoint("TOPLEFT", self.EditFrame.titleinputframe, "BOTTOMLEFT", 0, 0)
  self.EditFrame.desctext:SetText(L["Description/Notes:"])
  -- Create the ScrollFrame for the Description Edit Box
  self.EditFrame.descframe = CreateFrame("Frame", nil, self.EditFrame)
  self.EditFrame.descframe:SetWidth(300)
  self.EditFrame.descframe:SetHeight(67)
  self.EditFrame.descframe:SetBackdrop(backdrop2)
  self.EditFrame.descframe:SetPoint("TOPLEFT", self.EditFrame.desctext, "BOTTOMLEFT", 0, 0)
  self.EditFrame.descscrollframe = CreateFrame("ScrollFrame", "FlightHUD_EditScrollFrame",
    self.EditFrame.descframe, "UIPanelScrollFrameTemplate")
  self.EditFrame.descscrollframe:SetWidth(269)
  self.EditFrame.descscrollframe:SetHeight(59)
  self.EditFrame.descscrollframe:SetPoint("TOPLEFT", 5, -4)
  -- Create the Description Input Box and position it below the text
  self.EditFrame.descinputbox = CreateFrame("EditBox", nil, self.EditFrame)
  self.EditFrame.descinputbox:SetWidth(269) -- Height is auto set in a multiline editbox
  self.EditFrame.descinputbox:SetMaxLetters(512)
  self.EditFrame.descinputbox:SetNumeric(false)
  self.EditFrame.descinputbox:SetAutoFocus(false)
  self.EditFrame.descinputbox:SetFontObject("GameFontHighlightSmall")
  self.EditFrame.descinputbox:SetMultiLine(true)
  self.EditFrame.descinputbox:SetScript("OnCursorChanged", function(self, x, y, w, h)
    local scrollFrame = self:GetParent()
    local height = scrollFrame:GetHeight()
    local range = scrollFrame:GetVerticalScrollRange()
    local scroll = scrollFrame:GetVerticalScroll()
    local size = height + range
    local cursorOffset = -y
    while ( cursorOffset < scroll ) do
      scroll = (scroll - (height / 2))
      if ( scroll < 0 ) then
        scroll = 0
      end
      scrollFrame:SetVerticalScroll(scroll)
    end
    while ( (cursorOffset + h) > (scroll + height) and scroll < range ) do
      scroll = (scroll + (height / 2))
      if ( scroll > range ) then
        scroll = range
      end
      scrollFrame:SetVerticalScroll(scroll)
    end
  end)
  self.EditFrame.descinputbox:SetScript("OnEscapePressed", self.EditFrame.descinputbox.ClearFocus)
  -- Attach the ScrollChild to the ScrollFrame
  self.EditFrame.descscrollframe:SetScrollChild(self.EditFrame.descinputbox)
  -- Create the Icon Dropdown
  self.EditFrame.icondropdown = CreateFrame("Frame", "FlightHUD_IconDropDown", self.EditFrame, "UIDropDownMenuTemplate")
  self.EditFrame.icondropdown:SetPoint("TOPLEFT", self.EditFrame.descframe, "BOTTOMLEFT", -17, 0)
  self.EditFrame.icondropdown:SetHitRectInsets(16, 16, 0, 0)
  UIDropDownMenu_SetWidth(self.EditFrame.icondropdown,80)
  UIDropDownMenu_EnableDropDown(self.EditFrame.icondropdown)
  self.EditFrame.icondropdown.displayMode = "MENU"
  self.EditFrame.icondropdown.texture = self.EditFrame.icondropdown:CreateTexture(nil, "OVERLAY")
  self.EditFrame.icondropdown.texture:SetWidth(12)
  self.EditFrame.icondropdown.texture:SetHeight(12)
  self.EditFrame.icondropdown.texture:SetPoint("RIGHT", self.EditFrame.icondropdown, -41, 2)
  self.EditFrame.icondropdown.text = FlightHUD_IconDropDownText
  self.EditFrame.icondropdown.text:SetPoint("RIGHT", self.EditFrame.icondropdown.texture, "LEFT", -3, 0)
  self.EditFrame.icondropdown.OnClick = function(button,value)
    if type(button) ~= "table" then
      value = button
    end
    local t = icons[value]
    self.EditFrame.icondropdown.selectedValue = value
    self.EditFrame.icondropdown.texture:SetTexture(t.icon)
    if t.tCoordLeft then
      self.EditFrame.icondropdown.texture:SetTexCoord(t.tCoordLeft, t.tCoordRight, t.tCoordTop, t.tCoordBottom)
    else
      self.EditFrame.icondropdown.texture:SetTexCoord(0, 1, 0, 1)
    end
    self.EditFrame.icondropdown.text:SetText(t.text)
    local color = t.color
    if color then
      self.EditFrame.icondropdown.text:SetTextColor(color.r, color.g, color.b, color.a or 1)
    else
      self.EditFrame.icondropdown.text:SetTextColor(1, 1, 1, 1)
    end
  end
  self.EditFrame.icondropdown.initialize = function(level)
    for i = 1, #icons do
      local t = icons[i]
      info.text = t.text
      info.icon = t.icon
      local color = t.color
      info.textR = color and color.r or nil
      info.textG = color and color.g or nil
      info.textB = color and color.b or nil
      info.tCoordLeft = t.tCoordLeft or nil
      info.tCoordRight = t.tCoordRight or nil
      info.tCoordTop = t.tCoordTop or nil
      info.tCoordBottom = t.tCoordBottom or nil
      info.arg1 = i
      info.func = self.EditFrame.icondropdown.OnClick
      info.checked = self.EditFrame.icondropdown.selectedValue == i
      info.keepShownOnClick = nil
      UIDropDownMenu_AddButton(info)
    end
  end
  -- Create the zone display options dropdown
  self.EditFrame.zonedisplaydropdown = CreateFrame("Frame", "FlightHUD_ZoneDisplayDropDown", self.EditFrame, "UIDropDownMenuTemplate")
  self.EditFrame.zonedisplaydropdown:SetPoint("LEFT", self.EditFrame.icondropdown, "RIGHT", -28, 0)
  self.EditFrame.zonedisplaydropdown:SetHitRectInsets(16, 16, 0, 0)
  UIDropDownMenu_SetWidth(self.EditFrame.zonedisplaydropdown,80)
  UIDropDownMenu_EnableDropDown(self.EditFrame.zonedisplaydropdown)
  self.EditFrame.zonedisplaydropdown.displayMode = "MENU"
  self.EditFrame.zonedisplaydropdown.texture = self.EditFrame.zonedisplaydropdown:CreateTexture(nil, "OVERLAY")
  self.EditFrame.zonedisplaydropdown.texture:SetWidth(12)
  self.EditFrame.zonedisplaydropdown.texture:SetHeight(12)
  self.EditFrame.zonedisplaydropdown.texture:SetPoint("RIGHT", self.EditFrame.zonedisplaydropdown, -41, 2)
  self.EditFrame.zonedisplaydropdown.text = FlightHUD_ZoneDisplayDropDownText
  self.EditFrame.zonedisplaydropdown.text:SetPoint("RIGHT", self.EditFrame.zonedisplaydropdown.texture, "LEFT", -3, 0)
  self.EditFrame.zonedisplaydropdown.OnClick = function(button,value)
    self.EditFrame.zonedisplaydropdown.selectedValue = value
    self.EditFrame.zonedisplaydropdown.text:SetText(zonedisplayoptions[value])
  end
  self.EditFrame.zonedisplaydropdown.initialize = function(level)
    for i = 1, #zonedisplayoptions do
      zoneinfo.text = zonedisplayoptions[i]
      zoneinfo.arg1 = i
      zoneinfo.func = self.EditFrame.zonedisplaydropdown.OnClick
      zoneinfo.checked = self.EditFrame.zonedisplaydropdown.selectedValue == i
      zoneinfo.keepShownOnClick = nil
      UIDropDownMenu_AddButton(zoneinfo)
    end
  end
  -- Create the waypoint display options dropdown
  self.EditFrame.waypointdisplaydropdown = CreateFrame("Frame", "FlightHUD_WaypointDisplayDropDown", self.EditFrame, "UIDropDownMenuTemplate")
  self.EditFrame.waypointdisplaydropdown:SetPoint("LEFT", self.EditFrame.zonedisplaydropdown, "RIGHT", -28, 0)
  self.EditFrame.waypointdisplaydropdown:SetHitRectInsets(16, 16, 0, 0)
  UIDropDownMenu_SetWidth(self.EditFrame.waypointdisplaydropdown,80)
  UIDropDownMenu_EnableDropDown(self.EditFrame.waypointdisplaydropdown)
  self.EditFrame.waypointdisplaydropdown.displayMode = "MENU"
  self.EditFrame.waypointdisplaydropdown.texture = self.EditFrame.waypointdisplaydropdown:CreateTexture(nil, "OVERLAY")
  self.EditFrame.waypointdisplaydropdown.texture:SetWidth(12)
  self.EditFrame.waypointdisplaydropdown.texture:SetHeight(12)
  self.EditFrame.waypointdisplaydropdown.texture:SetPoint("RIGHT", self.EditFrame.waypointdisplaydropdown, -41, 2)
  self.EditFrame.waypointdisplaydropdown.text = FlightHUD_WaypointDisplayDropDownText
  self.EditFrame.waypointdisplaydropdown.text:SetPoint("RIGHT", self.EditFrame.waypointdisplaydropdown.texture, "LEFT", -3, 0)
  self.EditFrame.waypointdisplaydropdown.OnClick = function(button,value)
    self.EditFrame.waypointdisplaydropdown.selectedValue = value
    self.EditFrame.waypointdisplaydropdown.text:SetText(waypointdisplayoptions[value])
  end
  self.EditFrame.waypointdisplaydropdown.initialize = function(level)
    for i = 1, #waypointdisplayoptions do
      waypointinfo.text = waypointdisplayoptions[i]
      waypointinfo.arg1 = i
      waypointinfo.func = self.EditFrame.waypointdisplaydropdown.OnClick
      waypointinfo.checked = self.EditFrame.waypointdisplaydropdown.selectedValue == i
      waypointinfo.keepShownOnClick = nil
      UIDropDownMenu_AddButton(waypointinfo)
    end
  end
  -- Create the minimap checkbox
  self.EditFrame.minimapcheckbox = CreateFrame("CheckButton", nil, self.EditFrame, "UICheckButtonTemplate")
  self.EditFrame.minimapcheckbox:SetWidth(24)
  self.EditFrame.minimapcheckbox:SetHeight(24)
  self.EditFrame.minimapcheckbox:SetPoint("TOPRIGHT", self.EditFrame.icondropdown, "BOTTOMLEFT", 40, 0)
  self.EditFrame.minimapcheckbox.string = self.EditFrame.minimapcheckbox:CreateFontString()
  self.EditFrame.minimapcheckbox.string:SetWidth(200)
  self.EditFrame.minimapcheckbox.string:SetJustifyH("LEFT")
  self.EditFrame.minimapcheckbox.string:SetPoint("LEFT", 24, 1)
  self.EditFrame.minimapcheckbox:SetFontString(self.EditFrame.minimapcheckbox.string)
  self.EditFrame.minimapcheckbox:SetNormalFontObject("GameFontNormalSmall")
  self.EditFrame.minimapcheckbox:SetHighlightFontObject("GameFontHighlightSmall")
  self.EditFrame.minimapcheckbox:SetDisabledFontObject("GameFontDisableSmall")
  self.EditFrame.minimapcheckbox:SetText(L["Show on minimap"])
  self.EditFrame.minimapcheckbox:SetChecked(true)
  self.EditFrame.minimapcheckbox:SetHitRectInsets(0, -self.EditFrame.minimapcheckbox.string:GetStringWidth(), 0, 0)
  self.EditFrame.minimapcheckbox:SetPushedTextOffset(0, 0)
  -- Create the wolrdmap checkbox
  self.EditFrame.worldmapcheckbox = CreateFrame("CheckButton", nil, self.EditFrame, "UICheckButtonTemplate")
  self.EditFrame.worldmapcheckbox:SetWidth(24)
  self.EditFrame.worldmapcheckbox:SetHeight(24)
  self.EditFrame.worldmapcheckbox:SetPoint("LEFT", self.EditFrame.minimapcheckbox, "RIGHT", 130, 0)
  self.EditFrame.worldmapcheckbox.string = self.EditFrame.worldmapcheckbox:CreateFontString()
  self.EditFrame.worldmapcheckbox.string:SetWidth(200)
  self.EditFrame.worldmapcheckbox.string:SetJustifyH("LEFT")
  self.EditFrame.worldmapcheckbox.string:SetPoint("LEFT", 24, 1)
  self.EditFrame.worldmapcheckbox:SetFontString(self.EditFrame.worldmapcheckbox.string)
  self.EditFrame.worldmapcheckbox:SetNormalFontObject("GameFontNormalSmall")
  self.EditFrame.worldmapcheckbox:SetHighlightFontObject("GameFontHighlightSmall")
  self.EditFrame.worldmapcheckbox:SetDisabledFontObject("GameFontDisableSmall")
  self.EditFrame.worldmapcheckbox:SetText(L["Show on worldmap"])
  self.EditFrame.worldmapcheckbox:SetChecked(true)
  self.EditFrame.worldmapcheckbox:SetHitRectInsets(0, -self.EditFrame.worldmapcheckbox.string:GetStringWidth(), 0, 0)
  self.EditFrame.worldmapcheckbox:SetPushedTextOffset(0, 0)
  -- Create the permanent checkbox
  self.EditFrame.permanentcheckbox = CreateFrame("CheckButton", nil, self.EditFrame, "UICheckButtonTemplate")
  self.EditFrame.permanentcheckbox:SetWidth(24)
  self.EditFrame.permanentcheckbox:SetHeight(24)
  self.EditFrame.permanentcheckbox:SetPoint("TOPLEFT", self.EditFrame.minimapcheckbox, "BOTTOMLEFT", 0, 0)
  self.EditFrame.permanentcheckbox.string = self.EditFrame.permanentcheckbox:CreateFontString()
  self.EditFrame.permanentcheckbox.string:SetWidth(200)
  self.EditFrame.permanentcheckbox.string:SetJustifyH("LEFT")
  self.EditFrame.permanentcheckbox.string:SetPoint("LEFT", 24, 1)
  self.EditFrame.permanentcheckbox:SetFontString(self.EditFrame.permanentcheckbox.string)
  self.EditFrame.permanentcheckbox:SetNormalFontObject("GameFontNormalSmall")
  self.EditFrame.permanentcheckbox:SetHighlightFontObject("GameFontHighlightSmall")
  self.EditFrame.permanentcheckbox:SetDisabledFontObject("GameFontDisableSmall")
  self.EditFrame.permanentcheckbox:SetText(L["Permanent"])
  self.EditFrame.permanentcheckbox:SetChecked(true)
  self.EditFrame.permanentcheckbox:SetHitRectInsets(0, -self.EditFrame.permanentcheckbox.string:GetStringWidth(), 0, 0)
  self.EditFrame.permanentcheckbox:SetPushedTextOffset(0, 0)
  -- Create the characteronly checkbox
  self.EditFrame.characteronlycheckbox = CreateFrame("CheckButton", nil, self.EditFrame, "UICheckButtonTemplate")
  self.EditFrame.characteronlycheckbox:SetWidth(24)
  self.EditFrame.characteronlycheckbox:SetHeight(24)
  self.EditFrame.characteronlycheckbox:SetPoint("LEFT", self.EditFrame.permanentcheckbox, "RIGHT", 130, 0)
  self.EditFrame.characteronlycheckbox.string = self.EditFrame.characteronlycheckbox:CreateFontString()
  self.EditFrame.characteronlycheckbox.string:SetWidth(200)
  self.EditFrame.characteronlycheckbox.string:SetJustifyH("LEFT")
  self.EditFrame.characteronlycheckbox.string:SetPoint("LEFT", 24, 1)
  self.EditFrame.characteronlycheckbox:SetFontString(self.EditFrame.characteronlycheckbox.string)
  self.EditFrame.characteronlycheckbox:SetNormalFontObject("GameFontNormalSmall")
  self.EditFrame.characteronlycheckbox:SetHighlightFontObject("GameFontHighlightSmall")
  self.EditFrame.characteronlycheckbox:SetDisabledFontObject("GameFontDisableSmall")
  self.EditFrame.characteronlycheckbox:SetText(L["Character Specific"])
  self.EditFrame.characteronlycheckbox:SetChecked(true)
  self.EditFrame.characteronlycheckbox:SetHitRectInsets(0, -self.EditFrame.characteronlycheckbox.string:GetStringWidth(), 0, 0)
  self.EditFrame.characteronlycheckbox:SetPushedTextOffset(0, 0)
  -- Create the OK button
  self.EditFrame.okbutton = CreateFrame("Button", nil, self.EditFrame, "OptionsButtonTemplate")
  self.EditFrame.okbutton:SetWidth(150)
  self.EditFrame.okbutton:SetHeight(22)
  self.EditFrame.okbutton:SetPoint("TOPLEFT", self.EditFrame.permanentcheckbox, "BOTTOMLEFT", 0, 0)
  self.EditFrame.okbutton:SetText(OKAY)
  -- Create the Cancel button
  self.EditFrame.cancelbutton = CreateFrame("Button", nil, self.EditFrame, "OptionsButtonTemplate")
  self.EditFrame.cancelbutton:SetWidth(150)
  self.EditFrame.cancelbutton:SetHeight(22)
  self.EditFrame.cancelbutton:SetPoint("LEFT", self.EditFrame.okbutton, "RIGHT", 3, 0);
  self.EditFrame.cancelbutton:SetText(CANCEL)
  self.EditFrame.cancelbutton:SetScript("OnClick", self.EditFrame.CloseButton:GetScript("OnClick"))
  -- Additional Behavior functions
  self.EditFrame:SetScript("OnMouseDown", function(self, button)
    if MouseIsOver(FlightHUD.EditFrame.descframe) and button == "LeftButton" then
      FlightHUD.EditFrame.descinputbox:SetFocus()
    end
  end)
  self.EditFrame.titleinputbox:SetScript("OnTabPressed", function(self)
    FlightHUD.EditFrame.descinputbox:SetFocus()
  end)
  self.EditFrame.descinputbox:SetScript("OnTabPressed", function(self)
    FlightHUD.EditFrame.titleinputbox:SetFocus()
  end)
  ---------------------------------------------------------
  -- OnShow function to show a note for adding or editing
  self.EditFrame:SetScript("OnShow", function(self)
    FlightHUD.EditFrame.title:SetText(L["Add FlightHUD Waypoint"])
    FlightHUD.EditFrame.titleinputbox:SetText("")
    FlightHUD.EditFrame.descinputbox:SetText("")
    FlightHUD.EditFrame.icondropdown.OnClick(1)
    FlightHUD.EditFrame.permanentcheckbox:SetChecked(nil)
    FlightHUD.EditFrame.characteronlycheckbox:SetChecked(nil)
    FlightHUD.EditFrame.zonedisplaydropdown:OnClick(SHOW_IN_ZONE)
    FlightHUD.EditFrame.waypointdisplaydropdown:OnClick(SHOW_EVERYTHING)
    FlightHUD.EditFrame.minimapcheckbox:SetChecked(true)
    FlightHUD.EditFrame.worldmapcheckbox:SetChecked(true)
  end)
  ---------------------------------------------------------
  -- OnClick function to accept the changes for a new/edited note
  self.EditFrame.okbutton:SetScript("OnClick", function(self)
    FlightHUD.EditFrame:Hide()
    local data = {}
    data.t = false
    data.x = FlightHUD.EditFrame.x
    data.y = FlightHUD.EditFrame.y
    data.map = FlightHUD.EditFrame.map
    data.floor = FlightHUD.EditFrame.floor
    data.continent = FlightHUD.EditFrame.continent
    data.title = FlightHUD.EditFrame.titleinputbox:GetText()
    data.desc = FlightHUD.EditFrame.descinputbox:GetText()
    data.icon = FlightHUD.EditFrame.icondropdown.selectedValue
    data.permanent = (FlightHUD.EditFrame.permanentcheckbox:GetChecked() and true or false)
    data.characteronly = (FlightHUD.EditFrame.characteronlycheckbox:GetChecked() and true or false)
    data.zonedisplay = FlightHUD.EditFrame.zonedisplaydropdown.selectedValue
    data.waypointdisplay = FlightHUD.EditFrame.waypointdisplaydropdown.selectedValue
    data.minimap = (FlightHUD.EditFrame.minimapcheckbox:GetChecked() and true or false)
    data.worldmap = (FlightHUD.EditFrame.worldmapcheckbox:GetChecked() and true or false)
    AddWaypoint (data)
  end)
  -----------------------------------------------------------------------------------
  -- END -- (mostly) Verbatim HandyNotes code
  -----------------------------------------------------------------------------------
  self.FlightHUDFrame:RegisterForDrag("LeftButton")
  self.FlightHUDFrame:EnableMouse(false)
  self.FlightHUDFrame:SetMovable(false)
  self.FlightHUDFrame:SetScript("OnEvent",
    function(frame,event,...)
      if recursionCheck[event] then
        FlightHUD:DisplayError ()
        return
      end
      recursionCheck[event] = true
      FlightHUD[event](FlightHUD,...)
      recursionCheck[event] = false
    end
  )
  FlightHUD:FixDb()
  FlightHUD:EnableAddon ()
end

function FlightHUD:FixDb ()
  local showPopup = false
  for waypointid, waypoint in pairs (FlightHUD.db.profile.waypoints) do
    if not waypoint.dbversion or waypoint.dbversion < DBVERSION then
      showPopup = true
      FlightHUD.db.profile.staleWaypoints[waypointid] = waypoint
      FlightHUD.db.profile.waypoints[waypointid] = nil
    end
  end
  if showPopup then
    StaticPopup_Show ("FLIGHTHUD_CONFIRM_DBVERSION")
  end
end

function FlightHUD:DisplayError ()
  local errorText = debugstack (2)
  if FlightHUD.DisplayErrors then
    if FlightHUD.ErrorShowing then
      table.insert (FlightHUD.SavedErrors, #FlightHUD.SavedErrors + 1, errorText)
    else
      FlightHUD:ShowErrorDialog (errorText)
    end
  end
end

function FlightHUD:ShowErrorDialog (errorText)
  local f = AceGUI:Create("Frame")
  f:SetCallback("OnClose", function (widget)
    FlightHUD.ErrorShowing = false
    AceGUI:Release(widget)
    if FlightHUD.DisplayErrors and #FlightHUD.SavedErrors >= 1 then
      local errorText = FlightHUD.SavedErrors[1]
      FlightHUD:ShowErrorDialog (errorText)
      table.remove (FlightHUD.SavedErrors, 1)
    end
  end)
  f:SetTitle(L["FlightHUD Bug Report"])
  f:SetStatusText(L["Hit control-a to select all, then control-c to copy."])
  f:SetLayout("Fill")
  local e = AceGUI:Create("MultiLineEditBox")
  e:DisableButton(true)
  e:SetLabel(L["Backtrace"])
  e:SetText(errorText or "wtf?")
  e:SetFocus()
  f:AddChild(e)
  local b = AceGUI:Create("Button")
  b:SetText(L["Don't show any more errors."])
  b:SetWidth(300)
  b:SetCallback("OnClick", function()
    FlightHUD.SavedErrors = {}
    FlightHUD.DisplayErrors = false
  end)
  f:AddChild(b)
  FlightHUD.ErrorShowing = true
end

function FlightHUD:EnableAddon ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "DisableAddon", (FlightHUD.db.profile.DisableAddon and "true" or "false"))
  --@end-debug@
  if not FlightHUD.db.profile.DisableAddon then
    FlightHUD.FlightHUDFrame:SetScript("OnDragStart", FlightHUD.OnDragStart)
    FlightHUD.FlightHUDFrame:SetScript("OnDragStop", FlightHUD.OnDragStop)
    FlightHUD.FlightHUDFrame:SetScript("OnUpdate", FlightHUD.OnUpdate)
    FlightHUD.FlightHUDFrame:SetScript("OnShow", FlightHUD.OnShow)
    FlightHUD.FlightHUDFrame:SetScript("OnHide", FlightHUD.OnHide)
    FlightHUD.FlightHUDFrame:RegisterEvent("WORLD_MAP_UPDATE")
    FlightHUD.FlightHUDFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
    -- Only listen for this event if the frame is not locked
    if not FlightHUD.db.profile.LockPosition then
      FlightHUD.FlightHUDFrame:RegisterEvent("MODIFIER_STATE_CHANGED")
    end
    FlightHUD.FlightHUDFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
    if FlightHUD.db.profile.QuestPOI then
      FlightHUD.FlightHUDFrame:RegisterEvent("QUEST_POI_UPDATE")
      FlightHUD.FlightHUDFrame:RegisterEvent("QUEST_LOG_UPDATE")
    end
    -- Only run the event checking OnUpdate if we have events to track
    if not FlightHUD.db.profile.ShowAlways then
      FlightHUD.EventCheckFrame:SetScript("OnUpdate", FlightHUD.EventCheckOnUpdate)
    end
    hooksecurefunc("WatchFrame_Update", function()
      --@debug@
      FlightHUD:Debug (DEBUG1, "WatchFrame_Update")
      --@end-debug@
      if FlightHUD.db.profile.QuestPOI and not WatchFrame.collapsed then
        --@debug@
        FlightHUD:Debug (DEBUG2, "WatchFrame_Update", "  POI was enabled and the watch frame was NOT collapsed")
        --@end-debug@
        FlightHUD:ObjectivesChanged()
      end
      if WatchFrame.collapsed then
        --@debug@
        FlightHUD:Debug (DEBUG2, "WatchFrame_Update", "  The watch frame was collapsed")
        --@end-debug@
        FlightHUD:RemoveWaypoint (CurrentQuest, true)
        CurrentQuest = -1
      end
    end)

    FlightHUD:SetupQuestHelperCallback ()
    WorldMapButton:SetScript("OnMouseUp", WorldMapButton_OnClick)
    WorldMapButton:SetScript("OnShow", WorldMapButton_OnShow)
    WorldMapButton:SetScript("OnHide", WorldMapButton_OnHide)
    FlightHUD.enabled = true
    FlightHUD:EventCheck()
  else
    FlightHUD.FlightHUDFrame:SetScript("OnDragStart", nil)
    FlightHUD.FlightHUDFrame:SetScript("OnDragStop", nil)
    FlightHUD.FlightHUDFrame:SetScript("OnUpdate", nil)
    FlightHUD.FlightHUDFrame:SetScript("OnShow", nil)
    FlightHUD.FlightHUDFrame:SetScript("OnHide", nil)
    FlightHUD.FlightHUDFrame:UnregisterEvent("WORLD_MAP_UPDATE")
    FlightHUD.FlightHUDFrame:UnregisterEvent("ZONE_CHANGED_NEW_AREA")
    FlightHUD.FlightHUDFrame:UnregisterEvent("MODIFIER_STATE_CHANGED")
    FlightHUD.FlightHUDFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
    if FlightHUD.db.profile.QuestPOI then
      FlightHUD.FlightHUDFrame:UnregisterEvent("QUEST_POI_UPDATE")
      FlightHUD.FlightHUDFrame:UnregisterEvent("QUEST_LOG_UPDATE")
    end
    WorldMapButton:SetScript("OnMouseUp", orig_WorldMapButton_OnClick)
    WorldMapButton:SetScript("OnShow", orig_WorldMapButton_OnShow)
    WorldMapButton:SetScript("OnHide", orig_WorldMapButton_OnHide)
    FlightHUD.EventCheckFrame:SetScript("OnUpdate", nil)
    FlightHUD:RemoveQuestHelperCallback ()
    FlightHUD.FlightHUDFrame:Hide()
    FlightHUD.enabled = false
  end
end

function FlightHUD:ShouldShowWaypoint (waypoint)
  --@debug@
  FlightHUD:Debug(DEBUG1, "ShouldShowWaypoint")
  --@end-debug@
  local showIt = false
  -- Run through the stuff that makes the waypoint shown...
  if
    (not ForceContinentToggle and waypoint.zonedisplay == SHOW_IN_CONTINENT and waypoint.continent == GetCurrentMapContinent()) -- Show in continent, presumes the map isn't open already? FIXME!
    or (waypoint.zonedisplay == SHOW_IN_ZONE and waypoint.map == GetCurrentMapAreaID()) -- Show in zone
    or (not ForceContinentToggle and waypoint.zonedisplay == CONTINENT_NOT_ZONE and waypoint.continent == GetCurrentMapContinent() and waypoint.map ~= GetCurrentMapAreaID()) -- Continent, but not zone
  then
    showIt = true
  end
  -- ... then check if it should NOT be shown
  if
    (waypoint.zonedisplay == CONTINENT_NOT_ZONE and waypoint.map == GetCurrentMapAreaID()) -- Continent, but not zone
    or (waypoint.characteronly == SHOW_IN_CONTINENT and waypoint.playerName ~= playerName) -- Character only
  then
    showIt = false
  end
  --@debug@
  FlightHUD:Debug(DEBUG1, "ShouldShowWaypoint", "Returning: " .. (showIt and "true" or "false"))
  --@end-debug@
  return showIt
end

function FlightHUD:ShouldShowWorldmap (waypoint)
  local waypointframe = FlightHUD.waypointframes[waypoint.frameid]
  if waypointframe then
    if waypoint.worldmap and waypoint.map == GetCurrentMapAreaID() then
      waypointframe.worldmap:Show()
      waypointframe.worldmap.icon:Show()
      waypointframe.worldmap:SetScript("OnClick", FlightHUD.Mapicon_OnClick)
      waypointframe.worldmap:SetScript("OnEnter", FlightHUD.Mapicon_OnEnter)
      waypointframe.worldmap:SetScript("OnLeave", FlightHUD.Mapicon_OnLeave)
    else
      waypointframe.worldmap:Hide()
      waypointframe.worldmap.icon:Hide()
      waypointframe.worldmap:SetScript("OnClick", nil)
      waypointframe.worldmap:SetScript("OnEnter", nil)
      waypointframe.worldmap:SetScript("OnLeave", nil)
    end
  end
end

function FlightHUD:ShouldShowMinimap (waypoint)
  local waypointframe = FlightHUD.waypointframes[waypoint.frameid]
  if waypointframe then
    if waypoint.minimap and waypoint.map == GetCurrentMapAreaID() then
      waypointframe.minimap:Show()
      waypointframe.minimap.icon:Show()
      waypointframe.minimap:SetScript("OnClick", FlightHUD.Mapicon_OnClick)
      waypointframe.minimap:SetScript("OnEnter", FlightHUD.Mapicon_OnEnter)
      waypointframe.minimap:SetScript("OnLeave", FlightHUD.Mapicon_OnLeave)
    else
      waypointframe.minimap:Hide()
      waypointframe.minimap.icon:Hide()
      waypointframe.minimap:SetScript("OnClick", nil)
      waypointframe.minimap:SetScript("OnEnter", nil)
      waypointframe.minimap:SetScript("OnLeave", nil)
    end
  end
end

-- Event methods
function FlightHUD:MODIFIER_STATE_CHANGED(key, state)
  if not FlightHUD.db.profile.LockPosition then
    if (key == 'LCTRL' or key == 'RCTRL') and state == 1 then
      self.FlightHUDFrame:EnableMouse(true)
      self.FlightHUDFrame:SetMovable(true)
    else
      if (key == 'LCTRL' or key == 'RCTRL') and state == 0 then
        self.FlightHUDFrame:EnableMouse(false)
        self.FlightHUDFrame:SetMovable(false)
        self.FlightHUDFrame:StopMovingOrSizing()
      end
    end
  end
end

function FlightHUD:OnDragStart()
  self:StartMoving()
end

function FlightHUD:OnDragStop()
  self:StopMovingOrSizing()
  FlightHUD.db.profile.FramePoint_point,
  FlightHUD.db.profile.FramePoint_relativeTo,
  FlightHUD.db.profile.FramePoint_relativePoint,
  FlightHUD.db.profile.FramePoint_xOfs,
  FlightHUD.db.profile.FramePoint_yOfs = self:GetPoint()
end

function FlightHUD:OnEnable()
  self.enabled = true
end

function FlightHUD:OnDisable()
  self.enabled = false
end

function FlightHUD:ObjectivesChanged()
  -- Fix to account for odd C stack overflow issue. Thanks Archarodim!
  if AlreadyInObjectivesChanged then
    return
  end
  AlreadyInObjectivesChanged = true
  -- Again, borrowing from other addons, namely TomTomLite (I love you, jnwhiteh). Mostly verbatim
  --@debug@
  FlightHUD:Debug(DEBUG1, "ObjectivesChanged")
  --@end-debug@
  QuestPOIUpdateIcons()
  if CurrentQuest ~= -1 then
    FlightHUD:RemoveWaypoint (CurrentQuest, true)
    CurrentQuest = -1
  end
  local watchIndex = 1
  while true do
    -- Get the first quest item in the watch frame
    local questIndex = GetQuestIndexForWatch(watchIndex)
    -- FlightHUD.db.profile.QuestPOI's toggle calls this function to remove the waypoint
    if not questIndex or not FlightHUD.db.profile.QuestPOI then
      -- There are no quests being tracked. Remove the waypoint
      AlreadyInObjectivesChanged = false
      return
    end
    if questIndex then
      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, mapFloor = GetCurrentMapAreaID(), GetCurrentMapDungeonLevel()
        local complete = false
        if completed then
          title = "Turn in: " .. title
          complete = true
        end
        if x and y and map and mapFloor then
          FlightHUD:AddQWaypoint (map, mapFloor, x, y, title, L["Current Quest"], qid, complete)
        end
        AlreadyInObjectivesChanged = false
        return
      end
    end
    watchIndex = watchIndex + 1
  end
  AlreadyInObjectivesChanged = false
end

-- Other object methods
function FlightHUD:ResetPosition()
  FlightHUD.db.profile.FramePoint_point = false
  FlightHUD.db.profile.FramePoint_relativeTo = false
  FlightHUD.db.profile.FramePoint_relativePoint = false
  FlightHUD.db.profile.FramePoint_xOfs = false
  FlightHUD.db.profile.FramePoint_yOfs = false
  FlightHUD.FlightHUDFrame:ClearAllPoints()
  FlightHUD.FlightHUDFrame:SetPoint("CENTER")
end

function FlightHUD:ResetAll()
  FlightHUD.db:ResetProfile()
  local font = FlightHUD.PitchText:GetFont()
  FlightHUD.PitchText:SetFont(font, FlightHUD.db.profile.FontScale)
  FlightHUD.HeadingText:SetFont(font, FlightHUD.db.profile.FontScale)
  FlightHUD.CoordinatesText:SetFont(font, FlightHUD.db.profile.FontScale)
  FlightHUD.SpeedText:SetFont(font, FlightHUD.db.profile.FontScale)
  FlightHUD.CompassHeadingImage1:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.CompassHeadingImage2:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.PitchImage1:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.PitchImage2:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.ArtificialHorizonImage:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.HeadingCenterImage:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.HeadingText:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.PitchText:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.CoordinatesText:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.SpeedText:SetAlpha(FlightHUD.db.profile.HUDAlpha)
  FlightHUD.timage:SetAlpha(FlightHUD.db.profile.HUDBGAlpha)
  FlightHUD.FlightHUDFrame:SetScale(FlightHUD.db.profile.FrameScale)
  FlightHUD.FlightHUDFrame:ClearAllPoints()
  FlightHUD.FlightHUDFrame:SetPoint("CENTER")
end

function FlightHUD.EventCheckOnUpdate(frame, arg)
  EventCheckOnUpdateElapsed = EventCheckOnUpdateElapsed + arg
  if EventCheckOnUpdateElapsed > FlightHUD.db.profile.CheckRefreshRate then
    --@debug@
    FlightHUD:Debug(DEBUG1, "EventCheckOnUpdate")
    --@end-debug@
    FlightHUD.mounted = IsMounted()
    FlightHUD.swimming = IsSwimming()
    FlightHUD.flying = IsFlying()
    if FlightHUD.mounted ~= FlightHUD.LastMounted then
      FlightHUD:EventCheck ()
      FlightHUD.LastMounted = FlightHUD.mounted
    end
    if FlightHUD.swimming ~= FlightHUD.LastSwimming then
      FlightHUD:EventCheck ()
      FlightHUD.LastSwimming = FlightHUD.swimming
    end
    if FlightHUD.flying ~= FlightHUD.LastFlying then
      FlightHUD:EventCheck ()
      FlightHUD.LastFlying = FlightHUD.flying
    end
    EventCheckOnUpdateElapsed = 0
  end
end

function FlightHUD.OnUpdate (frame, arg)
  OnUpdateElapsed = OnUpdateElapsed + arg
  if OnUpdateElapsed > FlightHUD.db.profile.RefreshRate then
    -- Used by both compass graphic and heading text
    local facingRadians = GetPlayerFacing()
    local facingDegrees = math_deg (-facingRadians) % 360
    -- Compass graphic
    if (FlightHUD.ShowCompassImage) then
      if facingDegrees > 85 and facingDegrees < 268 then
        local rx = (facingDegrees / 360) + headingOffset
        local lx = rx - 0.5
        FlightHUD.CompassHeadingImage1:SetTexCoord(lx, 0, lx, 1, rx, 0, rx, 1)
        FlightHUD.CompassHeadingImage1:Show()
        FlightHUD.CompassHeadingImage2:Hide()
      else
        local newdegrees = 0
        if facingDegrees > 0 and facingDegrees < 180 then
          newdegrees = facingDegrees + 180
        else
          newdegrees = facingDegrees - 180
        end
        local rx = (newdegrees / 360) + headingOffset
        local lx = rx - 0.5
        FlightHUD.CompassHeadingImage2:SetTexCoord(lx, 0, lx, 1, rx, 0, rx, 1)
        FlightHUD.CompassHeadingImage1:Hide()
        FlightHUD.CompassHeadingImage2:Show()
      end
    end
    -- Heading text
    if (FlightHUD.db.profile.ShowHeadingText) then
      FlightHUD.HeadingText:SetText(format("%d", facingDegrees))
    end
    -- Used by both pitch graphic and pitch text
    local angle = math_deg (GetUnitPitch("player"))
    -- Pitch graphic
    local mult = 1
    if angle < 0 then
      mult = -1
    end
    if (FlightHUD.ShowPitchImage) then
      local newangle = -(angle % (mult * 180)) * 0.005
      local pgs = FlightHUD.db.profile.PitchGraphicsScale / 100
      local ax = newangle + 0.25 + pgs
      local ay = newangle + 0.75 - pgs
      local bx = newangle + (mult * FlightHUD.PitchFactor) + pgs
      local by = newangle + (mult * (FlightHUD.PitchFactor + .5)) - pgs
      FlightHUD.PitchImage1:SetTexCoord(0, ax, 0, ay, 1, ax, 1, ay)
      FlightHUD.PitchImage2:SetTexCoord(0, bx, 0, by, 1, bx, 1, by)
    end
    -- Pitch text
    if (FlightHUD.db.profile.ShowPitchText) then
      local displayAngle = angle
      if angle > 90 then
        displayAngle = -(180 - angle)
      end
      if angle < -90 then
        displayAngle = -(-180 - angle)
      end
      FlightHUD.PitchText:SetText(round (displayAngle, FlightHUD.db.profile.PitchPrecision))
    end
    -- Used by ShowCoordinatesText, and (ShowSpeedText or waypoint ETA)
    local map, floor, px, py = Astrolabe:GetCurrentPlayerPosition()
    if not floor then floor = 0 end
    if not map or not floor or not px or not py then
      return
    end
    -- Coordinates text
    if (FlightHUD.db.profile.ShowCoordinatesText) then
      FlightHUD.CoordinatesText:SetText(format("%d, %d", px * 100, py * 100))
    end
    -- Used in ETA calculation. If not set in the speed conditional, it must be obtained in the ETA calculator
    local etahorizspeed = 0
    local etahorizspeedobtained = false
    -- Speed text
    if (FlightHUD.db.profile.ShowSpeedText) then
      local speedtext = ""
      if (FlightHUD.db.profile.WhichSpeedType == "LEFT" or FlightHUD.db.profile.WhichSpeedType == "RIGHT") then
        local horizspeed = GetHorizontalSpeed (map, floor, px, py, arg)
        etahorizspeed = horizspeed / yardsdiv
        etahorizspeedobtained = true
        if (FlightHUD.db.profile.SpeedType == "BOTTOM") then
          horizspeed = round (horizspeed, FlightHUD.db.profile.SpeedPrecision) .. "%"
        end
        if (FlightHUD.db.profile.SpeedType == "LEFT") then
          horizspeed = round (horizspeed / yardsdiv, FlightHUD.db.profile.SpeedPrecision) .. L["y/s"]
        end
        if (FlightHUD.db.profile.SpeedType == "RIGHT") then
          horizspeed = round (horizspeed, FlightHUD.db.profile.SpeedPrecision) .. "%" .. "," ..
            round (horizspeed / yardsdiv, FlightHUD.db.profile.SpeedPrecision) .. L["y/s"]
        end
        if (FlightHUD.db.profile.ShowSpeedPrefix) then
          speedtext = L["H: "] .. horizspeed
        else
          speedtext = horizspeed
        end
      end
      -- True speed
      if (FlightHUD.db.profile.WhichSpeedType == "BOTTOM" or FlightHUD.db.profile.WhichSpeedType == "RIGHT") then
        local realspeed = GetUnitSpeed("player")
        if (FlightHUD.db.profile.SpeedType == "BOTTOM") then
          realspeed = round ((realspeed * yardsdiv), FlightHUD.db.profile.SpeedPrecision) .. "%"
        end
        if (FlightHUD.db.profile.SpeedType == "LEFT") then
          realspeed = round (realspeed, FlightHUD.db.profile.SpeedPrecision) .. L["y/s"]
        end
        if (FlightHUD.db.profile.SpeedType == "RIGHT") then
          realspeed = round ((realspeed * yardsdiv), FlightHUD.db.profile.SpeedPrecision) ..
            "%" .. "," .. round (realspeed, FlightHUD.db.profile.SpeedPrecision) .. L["y/s"]
        end
        if (speedtext ~= "") then
          speedtext = speedtext .. " - "
        end
        if (FlightHUD.db.profile.ShowSpeedPrefix) then
          speedtext = speedtext .. L["T: "] .. realspeed
        else
          speedtext = speedtext .. realspeed
        end
      end
      FlightHUD.SpeedText:SetText(speedtext)
    end
    -- Waypoints
    for frameid, waypointframe in pairs(FlightHUD.waypointframes) do
      if waypointframe.visible then
        local waypoint = waypointframe.waypoint
        local dist, x, y = Astrolabe:GetDistanceToIcon (waypointframe.minimap)
        if dist then
          -- Remove the non permanent, non-transient waypoint, as we're too close
          if dist < FlightHUD.db.profile.RemoveWaypointDistance then
            if not waypoint.permanent and not waypoint.t then
              FlightHUD:RemoveWaypoint (frameid, true)
            end
            -- Prevent sound spam if the waypoint is permanent
            local currtime = GetTime()
            if FlightHUD.db.profile.WaypointNotify and currtime - lastSound > FlightHUD.db.profile.WaypointNotifyInterval then
              lastSound = currtime
              PlaySoundFile(FlightHUD.db.profile.WaypointNotifySound)
            end
          else
            waypointframe.WaypointFrame:Show()
            -- This returns the direction of the icon relative to the player's
            -- map position in radians
            local directionRadians = Astrolabe:GetDirectionToIcon (waypointframe.minimap)
            -- Convert to degrees for text display
            local directionDegrees = math_deg (directionRadians)
            -- bearingRadians is used for math
            local bearingRadians = facingRadians - directionRadians
            -- bearingDegrees is for text representation
            local bearingDegrees = math_deg (bearingRadians) % 360
            -- Create a distance scaling factor
            local distscale = 0.55
            if (dist > 0 and dist < 50) then
              distscale = 1
            end
            if (dist > 50 and dist < 150) then
              distscale = 0.95
            end
            if (dist > 150 and dist < 300) then
              distscale = 0.9
            end
            if (dist > 300 and dist < 450) then
              distscale = 0.85
            end
            if (dist > 450 and dist < 600) then
              distscale = 0.8
            end
            if (dist > 600 and dist < 750) then
              distscale = 0.75
            end
            if (dist > 750 and dist < 900) then
              distscale = 0.7
            end
            if (dist > 900 and dist < 1050) then
              distscale = 0.65
            end
            if (dist > 1050 and dist < 1200) then
              distscale = 0.6
            end
            local bxmax = MainFrameWidthDiv / distscale
            local bx
            local by
            -- Display as an ellipse
            if (FlightHUD.db.profile.WaypointDisplay == "BOTTOM") then
              -- Semimajor axis
              local a = MainFrameWidthLess / distscale
              -- Semiminor axis
              local b = MainFrameHeightLess / distscale
              local temp = -bearingRadians + rad90
              bx = a * math_cos (temp)
              by = b * math_sin (temp)
            else
              -- Display along the parent frame (minus some arbitrary value)
              bx = bearingDegrees
              -- Calculate "by" to make it go up and down when the waypoint is in:
              -- The "fore" quadrant
              by = MainFrameHeightDiv
              -- The "port" quadrant
              if (bearingDegrees > 45 and bearingDegrees < 135) then
                -- This number needs to go from 0 to 90
                by = (90 - bearingDegrees) * byscale
              end
              -- The "starboard"s quadrant
              if (bearingDegrees < -45 and bearingDegrees > -135) then
                by = (90 - math_abs (bearingDegrees)) * byscale
              end
              -- The "aft" quadrant
              if (bearingDegrees > 135 or bearingDegrees < -135) then
                by = -MainFrameHeightDiv
                local mod = 180
                if (bearingDegrees < 0) then
                  mod = -180
                end
                -- bx (bearingDegrees still at this point) needs to go in reverse when in the aft quadrant
                bx = mod - bx
              end
              by = by / distscale
              -- Calculate bx
              local bx = (-bx * bxscale) / distscale
              if (bx > bxmax) then bx = bxmax end
              if (bx < -bxmax) then bx = -bxmax end
            end
            waypointframe.WaypointFrame:ClearAllPoints()
            waypointframe.WaypointFrame:SetScale (distscale)
            waypointframe.WaypointFrame:SetPoint ("CENTER", "FlightHUDFrame", "CENTER", bx, by)

            local etatext = ' '
            -- The user may have selected to not display horizontal speed. Get the horizontal speed
            -- in yards per second here.
            if not etahorizspeedobtained then
              etahorizspeed = GetHorizontalSpeed (map, floor, px, py, arg) / yardsdiv
            end
            -- If we have an ETA to display, calculate it, but only if we're facing it in a 90° arc
            -- Make this configurable?
            if
              etahorizspeed > 0
              and (bearingDegrees > FlightHUD.db.profile.etaArcL or
              bearingDegrees < FlightHUD.db.profile.etaArcR)
            then
              local totalseconds = math_floor (dist / etahorizspeed)
              local minutes = math_floor (totalseconds / 60)
              if (minutes > 0) then
                if (math_floor (minutes) == 1) then
                  etatext = format ("%d %s ", minutes, L["minute"])
                else
                  etatext = format ("%d %s ", minutes, L["minutes"])
                end
              end
              local seconds = totalseconds % 60
              if (math_floor (seconds) == 1) then
                etatext = format ("%s%d %s", etatext, seconds, L["second"])
              else
                etatext = format ("%s%d %s", etatext, seconds, L["seconds"])
              end
              if (etatext) then
                etatext = format ("%s %s", L["ETA: "], etatext)
              end
            end

            local DegreesText = L["degrees"]
            if (bearingDegrees >= 1 and bearingDegrees < 2) then
              DegreesText = L["degree"]
            end

            if waypoint.waypointdisplay == SHOW_EVERYTHING then
              waypointframe.TitleText:SetText(
                format(
                  "%s\n%d %s %d %s\n%s",
                  waypoint.title,
                  dist, L["yards"], bearingDegrees, DegreesText,
                  etatext
                )
              )
            end

            if waypoint.waypointdisplay == SHOW_DISTANCE_HEADING then
              waypointframe.TitleText:SetText(
                format(
                  "%s\n%d %s %d %s",
                  waypoint.title,
                  dist, L["yards"], bearingDegrees, DegreesText
                )
              )
            end

            if waypoint.waypointdisplay == SHOW_ETA then
              waypointframe.TitleText:SetText(
                format(
                  "%s\n%s",
                  waypoint.title,
                  etatext
                )
              )
            end

            if waypoint.waypointdisplay == SHOW_NOTHING then
              waypointframe.TitleText:SetText(
                format(
                  "%s",
                  waypoint.title
                )
              )
            end

          end
        else
          waypointframe.WaypointFrame:Hide()
        end
      end
    end
    OnUpdateElapsed = 0
  end
end

function FlightHUD:ResetWaypoints ()
  FlightHUD:RemoveAllWaypoints ()
  FlightHUD:AddAllWaypoints ()
end

function FlightHUD:AddAllWaypoints ()
  for waypointid, waypoint in pairs(FlightHUD.db.profile.waypoints) do
    AddWaypoint (waypoint)
  end
end

function FlightHUD:EventCheck ()
  local ShowFrame = false
  if
    (FlightHUD.db.profile.ShowCompassWhenFlying and FlightHUD.flying)
    or (FlightHUD.db.profile.ShowCompassWhenMounted and FlightHUD.mounted)
    or (FlightHUD.db.profile.ShowCompassWhenSwimming and FlightHUD.swimming)
    or FlightHUD.db.profile.ShowCompassAlways
  then
    FlightHUD.HeadingCenterImage:Show()
    FlightHUD.ShowCompassImage = true
  else
    FlightHUD.HeadingCenterImage:Hide()
    FlightHUD.CompassHeadingImage1:Hide()
    FlightHUD.CompassHeadingImage2:Hide()
    FlightHUD.ShowCompassImage = false
  end
  if
    (FlightHUD.db.profile.ShowPitchWhenFlying and FlightHUD.flying)
    or (FlightHUD.db.profile.ShowPitchWhenMounted and FlightHUD.mounted)
    or (FlightHUD.db.profile.ShowPitchWhenSwimming and FlightHUD.swimming)
    or FlightHUD.db.profile.ShowPitchAlways
  then
    FlightHUD.PitchImage1:Show()
    FlightHUD.PitchImage2:Show()
    FlightHUD.ArtificialHorizonImage:Show()
    FlightHUD.ShowPitchImage = true
  else
    FlightHUD.PitchImage1:Hide()
    FlightHUD.PitchImage2:Hide()
    FlightHUD.ArtificialHorizonImage:Hide()
    FlightHUD.ShowPitchImage = false
  end
  if
    (FlightHUD.db.profile.ShowWhenFlying and FlightHUD.flying)
    or (FlightHUD.db.profile.ShowWhenMounted and FlightHUD.mounted)
    or (FlightHUD.db.profile.ShowWhenSwimming and FlightHUD.swimming)
    or (FlightHUD.db.profile.ShowWhenSwimMount and FlightHUD.mounted and FlightHUD.swimming)
    or FlightHUD.db.profile.ShowAlways
  then
    ShowFrame = true
  end
  if ForceToggle == 1 then
    ShowFrame = true
  end
  if ForceToggle == 2 then
    ShowFrame = false
  end
  if ShowFrame and not FlightHUD.IsShowing then
    FlightHUD.FlightHUDFrame:Show()
    return
  end
  if not ShowFrame and FlightHUD.IsShowing then
    FlightHUD.FlightHUDFrame:Hide()
  end
end

function FlightHUD:ToggleHUD()
  --@debug@
  FlightHUD:Debug (DEBUG1, "ToggleHUD")
  FlightHUD:Debug (DEBUG2, "ToggleHUD", "current ForceToggle: " .. ForceToggle)
  --@end-debug@
  if not FlightHUD.enabled then
    --@debug@
    FlightHUD:Debug (DEBUG2, "ToggleHUD", "Addon was not enabled")
    --@end-debug@
    return
  end
  if ForceToggle == 1 or ForceToggle == 2 then
    --@debug@
    FlightHUD:Debug (DEBUG2, "ToggleHUD", "Setting to 0")
    --@end-debug@
    ForceToggle = 0
    return FlightHUD:EventCheck()
  end
  if not FlightHUD.IsShowing and ForceToggle == 0 then
    ForceToggle = 1
  end
  if FlightHUD.IsShowing and ForceToggle == 0 then
    ForceToggle = 2
  end
  --@debug@
  FlightHUD:Debug (DEBUG2, "ToggleHUD", "Setting to " .. ForceToggle)
  --@end-debug@
  FlightHUD:EventCheck()
end

function FlightHUD:ToggleContinent()
  --@debug@
  FlightHUD:Debug (DEBUG1, "ToggleContinent")
  FlightHUD:Debug (DEBUG2, "ToggleContinent", "current ForceContinentToggle: " .. (ForceContinentToggle and "true" or "false"))
  --@end-debug@
  ForceContinentToggle = not ForceContinentToggle
  --@debug@
  FlightHUD:Debug (DEBUG2, "ToggleContinent", "Setting to " .. (ForceContinentToggle and "true" or "false"))
  --@end-debug@
  FlightHUD:ResetWaypoints()
end

function FlightHUD:OnShow()
  --@debug@
  FlightHUD:Debug (DEBUG1, "OnShow")
  --@end-debug@
  FlightHUD.IsShowing = true
end

function FlightHUD:OnHide()
  --@debug@
  FlightHUD:Debug (DEBUG1, "OnHide")
  --@end-debug@
  FlightHUD.IsShowing = false
end

function FlightHUD:PLAYER_ENTERING_WORLD ()
  FlightHUD:ResetWaypoints()
end

function FlightHUD:DatabaseShutdown ()
  for waypointid, waypoint in pairs(FlightHUD.db.profile.waypoints) do
    if not waypoint.permanent then
      FlightHUD.db.profile.waypoints[waypointid] = nil
    end
  end
end

function FlightHUD:ZONE_CHANGED_NEW_AREA()
  --@debug@
  FlightHUD:Debug (DEBUG1, "ZONE_CHANGED_NEW_AREA")
  --@end-debug@
  FlightHUD.vars.speed = 0.0
  FlightHUD.vars.lastPos = {}
  FlightHUD.vars.lastTime = 0
  FlightHUD:ResetWaypoints()
  FlightHUD:WORLD_MAP_UPDATE ()
end

function FlightHUD:WORLD_MAP_UPDATE ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "WORLD_MAP_UPDATE")
  --@end-debug@
  if WorldMapFrame:IsShown() then
    for waypointid, waypoint in pairs (FlightHUD.db.profile.waypoints) do
      FlightHUD:ShouldShowWorldmap (waypoint)
    end
  end
end

function FlightHUD:QUEST_POI_UPDATE ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "QUEST_POI_UPDATE")
  --@end-debug@
  FlightHUD:ObjectivesChanged ()
end

function FlightHUD:QUEST_LOG_UPDATE ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "QUEST_LOG_UPDATE")
  --@end-debug@
  FlightHUD:ObjectivesChanged ()
end

function FlightHUD:Mapicon_OnClick ()
  FlightHUD.deleteWaypoint = self.frame.waypoint.frameid
  StaticPopup_Show ("FLIGHTHUD_CONFIRM_WAYPOINT_DELETE", self.frame.waypoint.title)
end

function FlightHUD:Mapicon_OnEnter ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "Mapicon_OnEnter")
  --@end-debug@
  GameTooltip_SetDefaultAnchor (GameTooltip, UIParent)
  GameTooltip:SetText (self.frame.waypoint.title)
  GameTooltip:AddLine (self.frame.waypoint.desc)
  GameTooltip:Show ()
end

function FlightHUD:Mapicon_OnLeave ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "Mapicon_OnLeave")
  --@end-debug@
  GameTooltip:Hide ()
end

function FlightHUD:AddQHWaypoint (map, floor, x, y, desc)
  --@debug@
  FlightHUD:Debug(DEBUG1, "AddQHWaypoint")
  --@end-debug@
  -- Somehow QuestHelper calls this with x being nil...
  if map and floor and x and y then
    FlightHUD:AddQWaypoint (map, floor, x, y, desc, L["QuestHelper Waypoint"], map .. floor .. x .. y, false)
  end
end

local InAddQWaypoint = false
function FlightHUD:AddQWaypoint (map, floor, x, y, desc, t, qid, complete)
  if InAddQWaypoint then
    FlightHUD:DisplayError ()
    InAddQWaypoint = false
    return
  end
  InAddQWaypoint = true
  --@debug@
  FlightHUD:Debug(DEBUG1, "AddQWaypoint")
  FlightHUD:Debug(DEBUG2, "AddQWaypoint", format ("  qid: %d, map: %d, floor: %d, x: %f, y: %f", qid or -1, map or -1, floor or -1, x or -1, y or -1))
  --@end-debug@
  if CurrentQuest ~= -1 then
    --@debug@
    FlightHUD:Debug(DEBUG2, "AddQWaypoint", "CurrentQuest frameid: " .. CurrentQuest)
    --@end-debug@
    -- Remove the current quest to make room for this one
    FlightHUD:RemoveWaypoint (CurrentQuest, true)
    CurrentQuest = -1
  end
  -- Make sure we have a valid point to track
  if not map then
    InAddQWaypoint = false
    return
  end
  local data = {}
  data.pid = pid
  data.t = true
  data.map = map
  data.x = x
  data.y = y
  data.floor = floor
  data.title = desc
  data.desc = t
  if complete then
    data.icon = 30
  else
    data.icon = 29
  end
  data.permanent = false
  data.zonedisplay = SHOW_IN_ZONE
  data.waypointdisplay = SHOW_EVERYTHING
  data.minimap = false
  data.worldmap = false
  CurrentQuest = AddWaypoint (data)
  InAddQWaypoint = false
end

function FlightHUD:RemoveWaypoint (frameid, delete)
  --@debug@
  FlightHUD:Debug(DEBUG1, "RemoveWaypoint", format ("frameid: %s", (frameid and frameid or "nil")))
  --@end-debug@
  if not frameid then
    -- The map click handler sets this
    frameid = FlightHUD.deleteWaypoint
    if not frameid then
      --@debug@
      FlightHUD:Debug(DEBUG2, "RemoveWaypoint", "No frameid. Returning.")
      --@end-debug@
      return
    end
    FlightHUD.deleteWaypoint = nil
  end
  --@debug@
  FlightHUD:Debug(DEBUG2, "RemoveWaypoint", "frameid: " .. frameid)
  --@end-debug@
  local waypointframe = FlightHUD.waypointframes[frameid]
  if not waypointframe then
    return
  end
  local waypoint = waypointframe.waypoint
  if not waypoint then
    return
  end
  Astrolabe:RemoveIconFromMinimap(waypoint.minimap)
  waypointframe.worldmap:Hide()
  waypointframe.minimap:Hide()
  waypointframe.WaypointFrame:Hide()
  waypointframe.inuse = false
  waypointframe.visible = false
  if delete then
    FlightHUD.db.profile.waypoints[waypoint.waypointid] = nil
  end
  waypointframe.waypoint = nil
end

function FlightHUD:RemoveAllWaypoints (all)
  --@debug@
  FlightHUD:Debug(DEBUG1, "RemoveAllWaypoints")
  --@end-debug@
  for frameid, waypointframe in pairs (FlightHUD.waypointframes) do
    FlightHUD:RemoveWaypoint (frameid, all)
  end
end

function FlightHUD:SetupQuestHelperCallback ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "SetupQuestHelperCallback")
  --@end-debug@
  if QuestHelper and not FlightHUD.CBid["qh"] and FlightHUD.db.profile.QuestHelper then
    FlightHUD.CBid["qh"] = QuestHelper:AddWaypointCallback (FlightHUD.AddQHWaypoint, FlightHUD)
  end
end

function FlightHUD:RemoveQuestHelperCallback ()
  --@debug@
  FlightHUD:Debug(DEBUG1, "RemoveQuestHelperCallback")
  --@end-debug@
  if FlightHUD.CBid["qh"] then
    QuestHelper:RemoveWaypointCallback (FlightHUD.CBid["qh"])
    -- Explicitly remove the existing waypoint, since removing the callback doesn't seem to do it
    FlightHUD:AddQHWaypoint ()
    FlightHUD.CBid["qh"] = nil
  end
end

--@debug@
function FlightHUD:Debug (level, type, arg)
  if
    FlightHUD.db.profile.EnableDebug
    and FlightHUD.db.profile.DebugTypes[type]
    and level <= FlightHUD.db.profile.DebugLevel
  then
    print (levels[level] .. "-" .. type .. ": " .. (arg and ": " .. arg or ""))
  end
end
--@end-debug@