local IC = InvenCraftInfo2
local map = CreateFrame("Frame", "InvenCraftInfo2_Map", UIParent, "UIPanelDialogTemplate")
local dummy = map:CreateTexture()
local npcName, zoneID, zoneName, zoneFile, floorName
local tilePath, numOverlays, width, height, offsetX, offsetY, numWidth, numHeight, pixelHeight, fileHeight, pixelWidth, fileWidth
local delimeter, coordX, coordY, numPins = ","

local _G = _G
local pairs = _G.pairs
local ceil = math.ceil
local floor = _G.math.floor

local function hasTexture(texture)
	dummy:SetTexture(texture)
	if dummy:GetTexture() then
		dummy:SetTexture(nil)
		return true
	end
	return nil
end

local function getZoneName(zone, level)
	if IC:LoadDB() then
		if level then
			floorName = _G["DUNGEON_FLOOR_"..zone..level]
			zone = IC:GetZone(zone)
			if floorName and zone ~= floorName then
				return zone.."("..floorName..")"
			else
				return zone
			end
		else
			return IC:GetZone(zone) or "알 수 없는 지역"
		end
	else
		return "알 수 없는 지역"
	end
end

local function pinOnHide(self)
	self.tooltip = nil
end

local function pinOnEnter(self)
	GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT")
	GameTooltip:AddLine(self.tooltip, 1, 1, 1)
	GameTooltip:Show()
end

local function setModel(id, name)
	if id then
		QuestFrame_ShowQuestPortrait(map, id, nil, name, 0, -90)
	elseif QuestNPCModel:GetParent() == self then
		QuestFrame_HideQuestPortrait()
	end
end

function map:SetNpc(id)
	if IC:LoadDB() then
		npcName, zoneID = IC:GetNpc(id)
		if npcName then
			zoneID = tonumber(zoneID)
			if zoneID > 0 then
				zoneName = self:SetMap(zoneID, self.npcLevel[id])
				if zoneName then
					self.title:SetFormattedText("Inven Craft Info 2 Map - %s (%s)", npcName, zoneName)
					if self.coords[id] and self.coords[id]:len() % 3 == 0 and self.coords[id]:find("^[0-9]+$") then
						self.pinParent:Show()
						self.instancePin:Hide()
						numPins = 0
						for i = 1, self.coords[id]:len(), 6 do
							numPins = numPins + 1
							if not self.pins[numPins] then
								self.pins[numPins] = CreateFrame("Button", nil, self.pinParent)
								self.pins[numPins]:SetSize(16, 16)
								self.pins[numPins]:SetNormalTexture("Interface\\WorldMap\\WorldMapPartyIcon")
								self.pins[numPins]:SetScript("OnHide", pinOnHide)
								self.pins[numPins]:SetScript("OnEnter", pinOnEnter)
								self.pins[numPins]:SetScript("OnLeave", GameTooltip_Hide)
								if self.pinParent.color then
									self.pins[numPins]:GetNormalTexture():SetVertexColor(1, 0, 0)
								else
									self.pins[numPins]:GetNormalTexture():SetVertexColor(1, 1, 1)
								end
							end
							coordX, coordY = tonumber(self.coords[id]:sub(i, i + 2)), tonumber(self.coords[id]:sub(i + 3, i + 5))
							self.pins[numPins].tooltip = ("%.01f, %.01f"):format(coordX / 10, coordY / 10)
							self.pins[numPins]:SetPoint("CENTER", self.pinParent, "TOPLEFT", coordX / 1000 * self.pinParent:GetWidth(), -coordY / 1000 * self.pinParent:GetHeight())
							self.pins[numPins]:Show()
						end
						for i = numPins + 1, #self.pins do
							self.pins[i]:Hide()
						end
						self.pinParent.num = numPins
					else
						self.pinParent:Hide()
						self.pinParent.num = 0
					end
					setModel(self.displayID[id], npcName)
					return true
				elseif self.instanceCoords[zoneID] then
					zoneName, coordX, coordY = delimeter:split(self.instanceCoords[zoneID])
					zoneName = self:SetMap(tonumber(zoneName))
					if zoneName then
						self.title:SetFormattedText("Inven Craft Info 2 Map - %s (%s)", npcName, getZoneName(zoneID))
						self.pinParent:Show()
						for i = 1, #self.pins do
							self.pins[i]:Hide()
						end
						coordX, coordY = tonumber(coordX), tonumber(coordY)
						self.instancePin.tooltip = ("%.01f, %.01f"):format(coordX / 10, coordY / 10)
						self.instancePin:SetPoint("CENTER", self.pinParent, "TOPLEFT", coordX / 1000 * self.pinParent:GetWidth(), -coordY / 1000 * self.pinParent:GetHeight())
						self.instancePin:Show()
						self.pinParent.num = 0
						setModel(self.displayID[id], npcName)
						return true
					end
				end
			end
		end
	end
	setModel()
	self:Hide()
	return nil
end

function map:SetMap(id, level)
	zoneFile = self.zoneFile[id]
	if zoneFile then
		tilePath = "Interface\\WorldMap\\"..zoneFile.."\\"..zoneFile
		if level then
			if hasTexture(tilePath..level.."_1") then
				tilePath = tilePath..level.."_"
			elseif hasTexture(tilePath.."1") then
				level = nil
			elseif hasTexture(tilePath.."1_1") then
				tilePath, level = tilePath.."1_", 1
			elseif hasTexture(tilePath.."0_1") then
				tilePath, level = tilePath.."0_", 0
			else
				self:Hide()
				return nil
			end
		elseif hasTexture(tilePath.."1") then
			level = nil
		elseif hasTexture(tilePath.."1_1") then
			tilePath, level = tilePath.."1_", 1
		elseif hasTexture(tilePath.."0_1") then
			tilePath, level = tilePath.."0_", 0
		else
			self:Hide()
			return nil
		end
		for i = 1, 12 do
			self.tiles[i]:SetTexture(tilePath..i)
		end
		if level or not self.mapOverlays[zoneFile] then
			self.detail:DisableDrawLayer("BORDER")
		else
			self.detail:EnableDrawLayer("BORDER")
			numOverlays = 0
			for file, info in pairs(self.mapOverlays[zoneFile]) do
				width = info % 1024
				height = floor(info / 1024) % 1024
				offsetX = floor(info / 1048576) % 1024
				offsetY = floor(info / 1073741824)
				numWidth = ceil(width / 256)
				numHeight = ceil(height / 256)
				for i = 1, numHeight do
					if i < numHeight then
						pixelHeight, fileHeight = 256, 256
					else
						pixelHeight = height % 256
						if pixelHeight == 0 then
							pixelHeight = 256
						end
						fileHeight = 16
						while fileHeight < pixelHeight do
							fileHeight = fileHeight * 2
						end
					end
					for j = 1, numWidth do
						if j < numWidth then
							pixelWidth, fileWidth = 256, 256
						else
							pixelWidth = width % 256
							if pixelWidth == 0 then
								pixelWidth = 256
							end
							fileWidth = 16
							while fileWidth < pixelWidth do
								fileWidth = fileWidth * 2
							end
						end
						numOverlays = numOverlays + 1
						self.overlays[numOverlays] = self.overlays[numOverlays] or self.detail:CreateTexture(nil, "BORDER")
						self.overlays[numOverlays]:SetSize(pixelWidth, pixelHeight)
						self.overlays[numOverlays]:SetTexCoord(0, pixelWidth / fileWidth, 0, pixelHeight / fileHeight)
						self.overlays[numOverlays]:SetPoint("TOPLEFT", offsetX + (256 * (j-1)), -(offsetY + (256 * (i - 1))))
						self.overlays[numOverlays]:SetTexture("Interface\\WorldMap\\"..zoneFile.."\\"..file..(((i - 1) * numWidth) + j))
						self.overlays[numOverlays]:Show()
					end
				end
			end
			for i = numOverlays + 1, #self.overlays do
				self.overlays[i]:Hide()
			end
			numOverlays, width, height, offsetX, offsetY, numWidth, numHeight, pixelHeight, fileHeight, pixelWidth, fileWidth = nil
		end
		self.pinParent.num = 0
		self:Show()
		return getZoneName(id, level)
	end
	self:Hide()
	return nil
end

tinsert(UISpecialFrames, map:GetName())
map:Hide()
map:SetFrameStrata(TradeSkillFrame:GetFrameStrata())
map:SetToplevel(true)
map:SetClampedToScreen(true)
map:EnableMouse(true)
map:SetMovable(true)
map:RegisterForDrag("LeftButton", "RightButton")
map:SetScript("OnDragStart", map.StartMoving)
map:SetScript("OnDragStop", map.StopMovingOrSizing)
map:SetScript("OnShow", function() PlaySound("igQuestLogOpen") end)
map:SetScript("OnHide", function() PlaySound("igQuestLogClose") end)
map:SetPoint("CENTER", 0, 0)
map:SetSize(567, 404)
map.detail = CreateFrame("Frame", nil, map)
map.detail:SetSize(1002, 668)
map.detail:SetScale(0.55)
map.detail:SetPoint("TOPLEFT", 17, -49)
map.pinParent = CreateFrame("Frame", nil, map)
map.pinParent:SetAllPoints(map.detail)
map.pinParent.timer = 0
map.pinParent:SetScript("OnUpdate", function(self, timer)
	self.timer = self.timer + timer
	if self.timer > 0.75 then
		self.timer = 0
		self.color = not self.color
		if self.color then
			for _, pin in pairs(map.pins) do
				pin:GetNormalTexture():SetVertexColor(1, 0, 0)
			end
			map.instancePin:GetNormalTexture():SetVertexColor(1, 0, 0)
		else
			for _, pin in pairs(map.pins) do
				pin:GetNormalTexture():SetVertexColor(1, 1, 1)
			end
			map.instancePin:GetNormalTexture():SetVertexColor(1, 1, 1)
		end
	end
end)
map.instancePin = CreateFrame("Button", nil, map.pinParent)
map.instancePin:SetSize(16, 16)
map.instancePin:SetNormalTexture("Interface\\FriendsFrame\\StatusIcon-Online")
map.instancePin:SetScript("OnHide", pinOnHide)
map.instancePin:SetScript("OnEnter", pinOnEnter)
map.instancePin:SetScript("OnLeave", GameTooltip_Hide)
map.tiles, map.overlays, map.pins = {}, {}, {}
for i = 1, 12 do
	map.tiles[i] = map.detail:CreateTexture(nil, "BACKGROUND")
	map.tiles[i]:SetSize(256, 256)
	if i == 1 then
		map.tiles[i]:SetPoint("TOPLEFT", 0, 0)
	elseif i % 4 == 1 then
		map.tiles[i]:SetPoint("TOPLEFT", map.tiles[i - 4], "BOTTOMLEFT")
	else
		map.tiles[i]:SetPoint("TOPLEFT", map.tiles[i - 1], "TOPRIGHT")
	end
end