local addonName, PakuHud = ...

local imageFolder = "Interface\\AddOns\\" .. addonName .. "\\Images\\"
local L = PakuHud.L
local Print = PakuHud.Print

local totemUnitId = "131154"

local ridingTotem = false
local mouseOverTotem = false

local defaultsSV = {
	frameDetails = {
		width = 512,
		height = 512,
		top = 0,
		left = 0,
		showAtMouse = true,
		anchorPoint = "TOPLEFT",
	},
	distanceTolerance = 50
}

-- Copy from table to another (used for copying default saved variables to real saved variables if not present)
local function copyDefaults(src, dst)
	if type(src) ~= "table" then return {} end
	if type(dst) ~= "table" then dst = {} end
	
	for k, v in pairs(src) do
		if type(v) == "table" then
			dst[k] = copyDefaults(v, dst[k])
		elseif type(v) ~= type(dst[k]) then
			Print("Found missing default [" .. k .. "] = " .. PakuHud.ToString(v))
			dst[k] = v
		end
	end
	
	return dst
end
	
PakuHud.Initialize = function()
	PakuHud.ImageFrame = PakuHud.CreateImageFrame()
	PakuHud.RegisterEvents()
end

PakuHud.Events = {}
PakuHud.Events.ADDON_LOADED = function(frame, addon)
	if addon == addonName then
		PakuHud.db = PakuHudDb
		
		-- Create an empty saved variables if not present
		if not PakuHud.db then
			PakuHud.db = {}
		end
		
		if not PakuHud.db.MissingTotems then
			PakuHud.db.MissingTotems = {}
		end
	
		copyDefaults(defaultsSV, PakuHud.db)
	end
	
	PakuHud.CreateOptionsFrame()

	frame:UnregisterEvent("ADDON_LOADED")
end

PakuHud.Events.PLAYER_LOGIN = function(frame, ...)
	PakuHud.SetFrameSize()
	PakuHud.SetFramePosition()
	
	GameTooltip:HookScript("OnTooltipSetUnit", function(tt)
		PakuHud.ReadTooltip(tt)
	end)

	GameTooltip:HookScript("OnUpdate", function(tt, elapsed)
		if mouseOverTotem and not PakuHud.IsGuidATotem(UnitGUID("mouseover")) then
			mouseOverTotem = false
			PakuHud.HideImageFrame()
		end
	end)
	
	frame:UnregisterEvent("PLAYER_LOGIN")
end

PakuHud.Events.PLAYER_LOGOUT = function(frame, ...)
	-- Save our local variables to PakuHudDb
	PakuHudDb = {}
	copyDefaults(PakuHud.db, PakuHudDb)
end

PakuHud.Events.UNIT_ENTERING_VEHICLE = function(frame, ...)
	local unitTarget,_,_,_,guid = ...
	if PakuHud.IsGuidATotem(guid) then
		local totem, distance = PakuHud.GetClosestTotem()
		if totem and not PakuHud.AlreadyHaveMissingTotem() then
			ridingTotem = true
			local missingTotem = {}
			local _, playerPosition = PakuHud.GetPlayerWorldPosition()
			missingTotem.startPoint = {}
			missingTotem.startPoint.x = playerPosition.x
			missingTotem.startPoint.y = playerPosition.y
			missingTotem.endPoint = {x = 0, y = 0}
			missingTotem.startMapDetails = C_Map.GetMapInfo(C_Map.GetBestMapForUnit("player"))
			missingTotem.startMinimapZoneText = GetMinimapZoneText();

			local numMissing = #PakuHud.db.MissingTotems
			PakuHud.db.MissingTotems[numMissing + 1] = missingTotem
		end
	end
end

PakuHud.Events.UNIT_EXITED_VEHICLE = function(frame, ...)
	if ridingTotem then
		local numMissing = #PakuHud.db.MissingTotems
		local _, playerPosition = PakuHud.GetPlayerWorldPosition()
		PakuHud.db.MissingTotems[numMissing].endPoint = {x = playerPosition.x, y = playerPosition.y}
		PakuHud.db.MissingTotems[numMissing].endMapDetails = C_Map.GetMapInfo(C_Map.GetBestMapForUnit("player"))
		PakuHud.db.MissingTotems[numMissing].endMinimapZoneText = GetMinimapZoneText();
		
		ridingTotem = false
	end
end

PakuHud.CreateImageFrame = function()
	local imageFrame = CreateFrame("Frame","PakuHudImageFrame",UIParent)
	imageFrame:SetFrameStrata("HIGH")
	imageFrame:EnableMouse(false)

	imageFrame.texture = imageFrame:CreateTexture()
	imageFrame.texture:SetAllPoints(imageFrame)
	imageFrame.texture:SetTexture(imageFolder .. "WholeMap")

	imageFrame.closeButton = CreateFrame("Button", "closeButton", imageFrame, "UIPanelButtonTemplate")
	imageFrame.closeButton:SetSize(25,25)
	imageFrame.closeButton:SetText("X")
	imageFrame.closeButton:SetPoint("TOPRIGHT",0,0)
	imageFrame.closeButton:SetScript("OnClick", function()
		imageFrame:Hide()
	end)
	
	imageFrame:Hide()
	return imageFrame
end

PakuHud.SetFrameSize = function()
	local fd = PakuHud.db.frameDetails
	PakuHud.ImageFrame:SetWidth(fd.width)
	PakuHud.ImageFrame:SetHeight(fd.width)
end

PakuHud.SetFramePosition = function()
	-- Start with clean slate
	PakuHud.ImageFrame:ClearAllPoints()
	
	local fd = PakuHud.db.frameDetails
	
	-- Check to see if we are supposed to show at mouse or anchor to top-left
	if (fd.showAtMouse) then
		local x = fd.left
		local y = fd.top

		local mouseX, mouseY = GetCursorPosition()
		local scale = PakuHud.ImageFrame:GetEffectiveScale()
		x = (mouseX / scale) + x
		y = (mouseY / scale) + y
		
		PakuHud.ImageFrame:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", x, y)
	else
		PakuHud.ImageFrame:SetPoint("TOPLEFT", fd.left, fd.top)
	end
end

PakuHud.ShowImageFrame = function(texture)
	PakuHud.SetFramePosition()
	PakuHud.ImageFrame.texture:SetTexture(imageFolder .. texture)
	PakuHud.ImageFrame:Show()
end

PakuHud.HideImageFrame = function()
	PakuHud.ImageFrame:Hide()
end

PakuHud.RegisterEvents = function()
	for k, v in pairs(PakuHud.Events) do
		PakuHud.ImageFrame:RegisterEvent(k)
	end
	PakuHud.ImageFrame:SetScript("OnEvent", function(self, event, ...)
		local handler = PakuHud.Events[event]
		if handler then
			handler(self, ...)
		end
	end)
end

PakuHud.ReadTooltip = function(tt)
	if not mouseOverTotem and PakuHud.IsGuidATotem(UnitGUID("mouseover")) then
		mouseOverTotem = true
		local totem, distance = PakuHud.GetClosestTotem()
		if totem then
			tt:AddLine(" ");
			tt:AddDoubleLine(L["From"], L[totem.startName]);
			tt:AddDoubleLine(L["To"], L[totem.endName]);
			
			PakuHud.ShowImageFrame(totem.image)
		end
	elseif mouseOverTotem then
		PakuHud.HideImageFrame()
		mouseOverTotem = false
	end
end

PakuHud.GetClosestTotem = function()
	local _, playerPosition = PakuHud.GetPlayerWorldPosition()
	local closestTotem = nil
	local closestDistance = PakuHud.db.distanceTolerance + 1
	for k,v in ipairs(PakuHud.TotemsDB) do
		local totemPos = v.startPoint
		local distanceToPlayer = PakuHud.DistanceSquared(playerPosition, totemPos)
		if distanceToPlayer < closestDistance then
			closestDistance = distanceToPlayer
			closestTotem = v
		end
	end
	
	return closestTotem, closestDistance
end

PakuHud.AlreadyHaveMissingTotem = function()
	local _, playerPosition = PakuHud.GetPlayerWorldPosition()
	local closestTotem = nil
	local closestDistance = PakuHud.db.distanceTolerance + 1
	
	for k,v in ipairs(PakuHud.db.MissingTotems) do
		local totemPos = v.startPoint
		local distanceToPlayer = PakuHud.DistanceSquared(playerPosition, totemPos)
		if distanceToPlayer < closestDistance then
			closestDistance = distanceToPlayer
			closestTotem = v
		end
	end
	
	return closestTotem ~= nil
end

PakuHud.IsGuidATotem = function(guid)
	if not guid then return false end

	--creatureType, _, serverId, instanceId, zoneId, unitId, spawnId = strsplit("-", guid)
	unitId = select(6, strsplit("-", guid))
	return unitId and unitId == totemUnitId
end

PakuHud.PrintMissingTotem = function(playerPosition)
	local msg = "PakuHud is missing the totem at this location. Please include these details:"
	local details = {}
	details.position = {}
	details.position.x = playerPosition.x
	details.position.y = playerPosition.y
	details.mapName = C_Map.GetMapInfo(C_Map.GetBestMapForUnit("player"), "player")
	
	Print(msg, details)
end

PakuHud.Initialize()

SLASH_PakuHud1, SLASH_PakuHud2, SLASH_PakuHud3 = '/PakuHud', '/paku', '/ph';
SlashCmdList["PakuHud"] = function(msg, editbox)
	local arg = string.lower(msg)
	if arg == "position" or arg == "pos" then
		PakuHud.PrintPlayerWorldPosition()
	elseif arg == "show" then
		PakuHud.ShowImageFrame("WholeMap")
	elseif arg == "hide" then
		PakuHud.HideImageFrame()
	elseif arg == "config" then
		-- Show options screen
	else
		Print("The following options are supported: show, hide, config")
	end
--[[
	if msg == "config" then
		--config:Show()
	else
		if imageFrame:IsShown() then
			imageFrame:Hide()
			closeButton:Hide()
			inConfig = false
		else
			imageFrame:EnableMouse(true)
			imageFrame:ClearAllPoints()
			imageFrame:SetPoint("CENTER",0,0)
			imageFrame.texture:SetTexture(imageFolder .. "WholeMap")
			imageFrame:Show()
			closeButton:Show()
			inConfig = true
		end
	end
	]]--
end