local AceOO = AceLibrary("AceOO-2.0")
local BZ = AceLibrary("Babble-Zone-2.2")

NotePoint = AceOO.Class(Waypoint)

NotePoint.prototype.Db = nil
NotePoint.prototype.Data = nil
NotePoint.prototype.ShowOnMap = true

local math_floor = math.floor
local function round(num, digits)
	-- banker's rounding
	local mantissa = 10^digits
	local norm = num*mantissa
	norm = norm + 0.5
	local norm_f = math_floor(norm)
	if norm == norm_f and (norm_f % 2) ~= 0 then
		return (norm_f-1)/mantissa
	end
	return norm_f/mantissa
end

local function getID(x, y)
	return round(x*10000, 0) + round(y*10000, 0)*10001
end

local function getXY(id)
	return (id % 10001)/10000, math_floor(id / 10001)/10000
end

-- Parse the id for the note and propogate the info
-- Possible inputs (zone, x, y) or (zone, id)
function NotePoint.prototype:init(zone, x, y, title)
	AceLibrary.argCheck(self, zone, 2, "string")
	AceLibrary.argCheck(self, x, 3, "number")			-- either a x-coord or an id
	AceLibrary.argCheck(self, y, 4, "nil", "number")	-- either a y-coord or nil
	AceLibrary.argCheck(self, title, 5, "string", "nil")
	

	if not BZ:HasTranslation(zone) then
		if BZ:HasReverseTranslation(zone) then
			zone = BZ:GetReverseTranslation(zone)
		else
			error(("Trying to set a waypoint with an unknown zone: %q"):format(zone), 2)
		end
	end
	local id
	if y then
		id = getID(x, y)
	else 
		id = x
		x,y = getXY(id)
	end
	NotePoint.super.prototype.init(self, id..zone)
	if not title then
		self.Zone, self.x, self.y, _, self.Db, self.Data = Cartographer_Notes:GetNote(zone, x, y)
	else
		self.Zone, self.x, self.y, self.Data = zone, x, y, {title = title}
	end	
end

-- Is this the same note as the waypoint?
function NotePoint.prototype:MatchNote(id)
	return self.WaypointID == id
end
	
-- Use the data.title as the name of the note, otherwise the zone
function NotePoint.prototype:ToString()
	if self.Data then 
		if not self.Data.title then
			if self.Data.icon then
				return self.Data.icon
			end
		else
			return self.Data.title
		end
	else
		return "Waypoint"
	end
end

function NotePoint.prototype:GetDistance()
	return Cartographer:GetDistanceToPoint(self.x, self.y, self.Zone)
end

function NotePoint.prototype:Cancel()
	NotePoint.super.prototype.Cancel(self)
	self.Db, self.Data = nil
end

function NotePoint.prototype:IsValid()
	if self.Zone == "Limbo" then return false end
	if self.Data.title or Cartographer_Notes:GetNote(self.Zone, self.x, self.y) then
		return true
	else
		return false
	end
end

function NotePoint.prototype:ShowOnMap()
	return true
end
