-- MetaMapWKB
-- Written by MetaHawk - aka Urshurak

MetaKB_dbID = "db1.1";
METAKB_AUTHOR = "MetaMapWKB";

METAKB_SCROLL_FRAME_BUTTON_HEIGHT = 16;
METAKB_SCROLL_FRAME_BUTTONS_SHOWN = 20;
METAKB_SORTBY_NAME = "name";
METAKB_SORTBY_DESC = "desc";
METAKB_SORTBY_LEVEL = "level";
METAKB_SORTBY_LOCATION = "location";

MetaKB_Data = {};
MetaKB_Data[MetaKB_dbID] = {};
MetaKBOptions = {};
MetaKB_List = {};

MetaKB_overRide = false;
MetaKB_ShowAllZones = false;
MetaKB_ScrollFrameButtonID = 0;
MetaKB_VarsLoaded = false;

local MetaKB_LastSearch = "";
local MetaKB_SearchResults = {};
local MetaKB_PlayerX = 0;
local MetaKB_PlayerY = 0;

function MetaKB_MainFrame_OnLoad()
	this:RegisterEvent("ADDON_LOADED");
	this:RegisterEvent("WORLD_MAP_UPDATE");
	this:RegisterEvent("ZONE_CHANGED_NEW_AREA");
	this:RegisterEvent("UPDATE_MOUSEOVER_UNIT");
end
function MetaKB_OnEvent(event)
	if(event == "ADDON_LOADED" and arg1 == "MetaMapWKB") then
		if(MetaKBOptions.ShowUpdates == nil) then MetaKBOptions.ShowUpdates = false; end
		if(MetaKBOptions.CreateMapNotesBoundingBox == nil) then MetaKBOptions.CreateMapNotesBoundingBox = true; end
		if(MetaKBOptions.AutoTrack == nil) then MetaKBOptions.AutoTrack = false; end
		if(MetaKBOptions.KBstate == nil) then MetaKBOptions.KBstate = false; end
		if(MetaKBOptions.NewTargetNote == nil) then MetaKBOptions.NewTargetNote = false; end
		if(MetaKBOptions.RangeCheck == nil) then MetaKBOptions.RangeCheck = 1; end
		if(MetaKBOptions.Dsearch == nil) then MetaKBOptions.Dsearch = true; end
		if(MetaKBOptions.EmbedKB == nil) then MetaKBOptions.EmbedKB = true; end
		if(MetaKBOptions.SetMapShow == nil) then MetaKBOptions.SetMapShow = false; end
		MetaMapWKB_OptionsDialogInit();
		MetaMapWKB_VerifyData();
		MetaKB_InitFrame();
	end
	if(event == "INSTANCE_MAP_UPDATE" and WorldMapFrame:IsVisible()) then
		if(MetaKB_DisplayFrame:IsVisible() and MetaKBOptions.EmbedKB and not MetaKB_ShowAllZones) then
			MetaKB_Search();
		else
			MetaMapContainerFrame:Hide();
		end
	end
	if(event == "WORLD_MAP_UPDATE" and WorldMapFrame:IsVisible()) then
		if(MetaKB_DisplayFrame:IsVisible() and MetaKBOptions.EmbedKB and not MetaKB_ShowAllZones) then
			MetaKB_Search();
		else
			MetaMapContainerFrame:Hide();
		end
	end
	if(event == "ZONE_CHANGED_NEW_AREA") then
		if(MetaKB_DisplayFrame:IsVisible() and not MetaKB_ShowAllZones) then
			MetaKB_Search();
		end
	end
	if(event == "UPDATE_MOUSEOVER_UNIT" and MetaKBOptions.AutoTrack) then
		if(UnitIsPlayer("mouseover")~=1 and UnitPlayerControlled("mouseover")~=1 and UnitIsDead("mouseover")~=1) then
			MetaKB_AddUnitInfo("mouseover");
		end
	end
end

function MetaMapWKB_OptionsDialogInit()
	MetaKB_AlwaysOnCheckButton:SetChecked(MetaMapOptions.WKBalwaysOn);
	MetaKB_ShowUpdatesCheckButton:SetChecked(MetaKBOptions.ShowUpdates);
	MetaKB_BoundingBoxCheckButton:SetChecked(MetaKBOptions.CreateMapNotesBoundingBox);
	MetaKB_AutoTrackingCheckButton:SetChecked(MetaKBOptions.AutoTrack);
	MetaKB_DsearchCheckButton:SetChecked(MetaKBOptions.Dsearch);
	MetaKB_UseKBCheckButton:SetChecked(MetaKBOptions.KBstate);
	MetaKB_SetTargetNoteCheckButton:SetChecked(MetaKBOptions.NewTargetNote);
	MetaKB_SetMapShowCheckButton:SetChecked(MetaKBOptions.SetMapShow);
	MetaKB_EmbedCheckButton:SetChecked(MetaKBOptions.EmbedKB);
	MetaKB_ToggleSetRange(MetaKBOptions.RangeCheck);
end

function MetaKB_InitFrame()
	if(MetaKBOptions.EmbedKB) then
		MetaKB_DisplayFrame:SetParent("MetaMapContainerFrame");
		MetaKB_DisplayFrame:SetPoint("CENTER", "MetaMapContainerFrame", "CENTER", 0, 0);
		MetaKB_DisplayFrame:SetWidth(MetaMapContainerFrame:GetWidth());
		MetaKB_DisplayFrame:SetHeight(MetaMapContainerFrame:GetHeight());
		MetaKB_HeaderPanel:SetHeight(40);
		MetaKB_FooterPanel:SetHeight(60);
		MetaKB_CloseMainFrameButton:Hide();
		METAKB_SCROLL_FRAME_BUTTON_HEIGHT = 18;
		METAKB_SCROLL_FRAME_BUTTONS_SHOWN = 30;
	else
		MetaKB_DisplayFrame:SetParent("MetaKB_OuterFrame");
		MetaKB_DisplayFrame:SetPoint("CENTER", "MetaKB_OuterFrame", "CENTER", 0, 0);
		MetaKB_DisplayFrame:SetWidth(710);
		MetaKB_DisplayFrame:SetHeight(370);
		MetaKB_HeaderPanel:SetHeight(22);
		MetaKB_FooterPanel:SetHeight(40);
		MetaKB_CloseMainFrameButton:Show();
		METAKB_SCROLL_FRAME_BUTTON_HEIGHT = 16;
		METAKB_SCROLL_FRAME_BUTTONS_SHOWN = 20;
	end
	MetaKB_HeaderPanel:SetWidth(MetaKB_HeaderPanel:GetParent():GetWidth());
	MetaKB_HeaderPanel:SetFrameLevel(MetaKB_HeaderPanel:GetParent():GetFrameLevel()+1);
	MetaKB_FooterPanel:SetWidth(MetaKB_FooterPanel:GetParent():GetWidth());
	MetaKB_FooterPanel:SetFrameLevel(MetaKB_FooterPanel:GetParent():GetFrameLevel()+1);
	MetaKB_ScrollFrame:SetHeight(MetaKB_ScrollFrame:GetParent():GetHeight() - (MetaKB_HeaderPanel:GetHeight()+MetaKB_FooterPanel:GetHeight()));
	MetaKB_ScrollFrame:SetWidth(MetaKB_ScrollFrame:GetParent():GetWidth()-22);
	MetaKB_Header1:SetWidth(MetaKB_HeaderPanel:GetWidth()*0.2675);
	MetaKB_Header2:SetWidth(MetaKB_HeaderPanel:GetWidth()*0.38);
	MetaKB_Header3:SetWidth(MetaKB_HeaderPanel:GetWidth()*0.16);
	MetaKB_Header4:SetWidth(MetaKB_HeaderPanel:GetWidth()*0.20);
	for i=1, METAKB_SCROLL_FRAME_BUTTONS_SHOWN,1 do
		getglobal("MetaKB_ScrollFrameButton"..i.."Name"):SetWidth(MetaKB_Header1:GetWidth());
		getglobal("MetaKB_ScrollFrameButton"..i.."Info1"):SetWidth(MetaKB_Header2:GetWidth());
		getglobal("MetaKB_ScrollFrameButton"..i.."Info2"):SetWidth(MetaKB_Header3:GetWidth());
		getglobal("MetaKB_ScrollFrameButton"..i.."Coords"):SetWidth(MetaKB_Header4:GetWidth());
	end
end

function MetaMapWKB_VerifyData()
	local TempData = {}
	TempData[MetaKB_dbID] = {};
	for name, continentTable in MetaKB_Data[MetaKB_dbID] do
		for continent, zoneTable in continentTable do
			if(type(continent) ~= "String") then
				for zone, value in zoneTable do
					if(zone ~= 0) then
						TempData[MetaKB_dbID][name] = {};
						TempData[MetaKB_dbID][name][continent] = {};
						TempData[MetaKB_dbID][name][continent][zone] = {};
						TempData[MetaKB_dbID][name][continent][zone] = value;
					end
				end
			end
		end
	end
	MetaKB_Data = {};
	MetaKB_Data[MetaKB_dbID] = {};
	MetaKB_Data[MetaKB_dbID] = TempData[MetaKB_dbID];
	TempData = nil;
end

function MetaKB_ToggleFrame(mode)
	if(MetaKBOptions.EmbedKB) then
		if(MetaKB_DisplayFrame:IsVisible()) then
			MetaMapContainer_ShowFrame();
			if(mode == 1) then
				MetaMap_ToggleFrame(WorldMapFrame);
			end
		else
			if(not WorldMapFrame:IsVisible()) then
				MetaMap_ToggleFrame(WorldMapFrame);
			end
			MetaMapContainer_ShowFrame(MetaKB_DisplayFrame);
		end
	else
		MetaMap_ToggleFrame(MetaKB_DisplayFrame:GetParent());
	end
end

function MetaKB_StripTextColors(textString)
	-- this function is designed to replace
	-- |cff00AA00Colored Text|r with Colored Text
	if(textString ~= nil and textString ~= "") then
		return string.gsub(textString, "|c[%dA-Fa-f][%dA-Fa-f][%dA-Fa-f][%dA-Fa-f][%dA-Fa-f]"..
				"[%dA-Fa-f][%dA-Fa-f][%dA-Fa-f](.*)|r", "%1");
	else
		assert(false, "nil or invalid parameter to StripTextColors");
	end
end

function MetaKB_ToggleSetRange(range)
	for i=1, 5 do
		if(i == range) then
			local checkButton = getglobal("MetaKB_RangeCheck"..i);
			checkButton:SetChecked(true);
		else
			local checkButton = getglobal("MetaKB_RangeCheck"..i);
			checkButton:SetChecked(false);
		end
	end
	MetaKBOptions.RangeCheck = range;
end

function MetaKB_UpdateKeySelectedUnit()
	if (not UnitExists("target")) then
		MetaMap_StatusPrint(METAKB_NOTARGET,MetaKBOptions.ShowUpdates);
		return;
	else
		if(IsControlKeyDown()) then
			MetaKB_overRide = true;
		end
		MetaKB_AddUnitInfo("target");
			MetaKB_overRide = false;
	end
end

function MetaKB_AddUnitInfo(UnitSelect)
	if( not CheckInteractDistance(UnitSelect, MetaKBOptions.RangeCheck) and MetaKBOptions.RangeCheck ~= 5) then
		return;
	end
	local continent, zone = MetaMap_NameToZoneID(GetRealZoneText());
	if(type(continent) == "string") then
		MetaMap_StatusPrint(METAMAPNOTES_INVALIDZONE, MetaKBOptions.ShowUpdates);
		return;
	end
	local icon = 3; --green by default
	local unitName = UnitName(UnitSelect);
	local ncol = 0;
	local desc1 = "";
	local desc2 = "";
	local playerX, playerY = GetPlayerMapPosition("player")

	playerX = MetaMap_round(playerX*10000)
	playerY = MetaMap_round(playerY*10000)
	unitName = MetaKB_StripTextColors(unitName);

	if(UnitReaction("player", UnitSelect) < 4) then
		if(UnitClassification(UnitSelect) ~= "normal") then
			desc1 = UnitClassification(UnitSelect).." ";
		end
		if(UnitCreatureType(UnitSelect) ~= nil) then
			desc1 = desc1..UnitCreatureType(UnitSelect).." "
		end
		if(UnitClass(UnitSelect) ~= nil) then
			desc1 = desc1..UnitClass(UnitSelect);
		end
		if(UnitLevel(UnitSelect) == "-1") then
			desc2 = METAKB_MOB_LEVEL.." ??";
		else
			desc2 = METAKB_MOB_LEVEL.." "..UnitLevel(UnitSelect);
		end
		icon = 1;
	elseif(UnitReaction("player", UnitSelect) == 4) then
		if(GameTooltipTextLeft2:GetText() ~= nil) then
			desc1 = string.sub(GameTooltipTextLeft2:GetText(), 9);
		end
		desc2 = METAKB_MOB_LEVEL.." "..UnitLevel(UnitSelect);
		icon = 0;
	elseif(UnitReaction("player", UnitSelect) > 4 and UnitIsPlayer(UnitSelect)) then
		unitName = UnitPVPName(UnitSelect);
		desc1 = UnitRace(UnitSelect).." "..UnitClass(UnitSelect);
		desc2 = METAKB_MOB_LEVEL.." "..UnitLevel(UnitSelect);
		icon = 7;
	elseif(UnitReaction("player", UnitSelect) < 4 and UnitIsPlayer(UnitSelect)) then
		unitName = UnitPVPName(UnitSelect);
		desc1 = UnitRace(UnitSelect).." "..UnitClass(UnitSelect);
		desc2 = METAKB_MOB_LEVEL.." "..UnitLevel(UnitSelect);
		icon = 6;
	else
		local check = GameTooltipTextLeft2:GetText();
		if (check ~= nil) then
			if(string.find(check, METAKB_MOB_LEVEL)) then
				if(GameTooltipTextLeft3 ~= "" and GameTooltipTextLeft3 ~= nil) then
					desc1 = GameTooltipTextLeft3:GetText();
					desc2 = GameTooltipTextLeft2:GetText();
				end
			else
				if(GameTooltipTextLeft2 ~= "" and GameTooltipTextLeft2 ~= nil) then
					desc1 = GameTooltipTextLeft2:GetText();
				end
				if(GameTooltipTextLeft3 ~= "" and GameTooltipTextLeft3 ~= nil) then
					desc2 = GameTooltipTextLeft3:GetText();
				end
			end
		end
		icon = 3;
	end
	if(desc1 == nil) then desc1 = ""; end
	if(desc2 == nil) then desc2 = ""; end

	local changedSomething = false;
	local addedSomething = false;
	local updatedSomething = false;
	local currentUnit;

	if(MetaKB_Data[MetaKB_dbID][unitName] == nil) then
		MetaKB_Data[MetaKB_dbID][unitName] = {};
		MetaMap_StatusPrint(format(TEXT(METAKB_DISCOVERED_UNIT), unitName), true);
	end
	currentUnit = MetaKB_Data[MetaKB_dbID][unitName];
	if(currentUnit[continent] == nil) then
		currentUnit[continent] = {};
	end
	if(currentUnit[continent][zone] == nil) then
		currentUnit[continent][zone] = {};
		currentUnit[continent][zone]["inf1"] = desc1;
		currentUnit[continent][zone]["inf2"] = desc2;
		currentUnit[continent][zone]["icon"] = icon;
		currentUnit[continent][zone][1] = 20000;
		currentUnit[continent][zone][2] = -1;
		currentUnit[continent][zone][3] = -1;
		currentUnit[continent][zone][4] = 20000;
		addedSomething = true
	else
		currentUnit[continent][zone]["icon"] = icon;
		if(currentUnit[continent][zone]["inf1"] == "") then
			currentUnit[continent][zone]["inf1"] = desc1;
			updatedSomething = true;
		end
		if(currentUnit[continent][zone]["inf2"] == "") then
			currentUnit[continent][zone]["inf2"] = desc2;
			updatedSomething = true;
		end
	end		

	local coords = currentUnit[continent][zone];

	if(playerX < coords[4]) then
		currentUnit[continent][zone][4] = playerX;
		changedSomething = true;
	end
	if(playerY < coords[1]) then
		currentUnit[continent][zone][1] = playerY;
		changedSomething = true;
	end
	if(playerX > coords[2]) then
		currentUnit[continent][zone][2] = playerX;
		changedSomething = true;
	end
	if(playerY > coords[3]) then
		currentUnit[continent][zone][3] = playerY;
		changedSomething = true;
	end

	if(MetaKBOptions.NewTargetNote or MetaKB_overRide) then
		MetaKB_AddMapNotes(unitName, GetRealZoneText(), 0);
	end
	if(MetaKBOptions.KBstate) then
		if(addedSomething) then
			MetaMap_StatusPrint(format(TEXT(METAKB_ADDED_UNIT_IN_ZONE), unitName, GetRealZoneText()), MetaKBOptions.ShowUpdates);
		end
		if(changedSomething and not addedSomething) then
			MetaMap_StatusPrint(format(TEXT(METAKB_UPDATED_MINMAX_XY), unitName, GetRealZoneText()), MetaKBOptions.ShowUpdates);
		end
		if(updatedSomething) then
			MetaMap_StatusPrint(format(TEXT(METAKB_UPDATED_INFO), unitName, GetRealZoneText()), MetaKBOptions.ShowUpdates);
		end
	else
		currentUnit = nil;
	end
end

function MetaKB_UpdateScrollFrame()
	for iScrollFrameButton = 1, METAKB_SCROLL_FRAME_BUTTONS_SHOWN, 1 do
		local buttonIndex = iScrollFrameButton + FauxScrollFrame_GetOffset(MetaKB_ScrollFrame);
		local scrollFrameButton = getglobal("MetaKB_ScrollFrameButton"..iScrollFrameButton);
		local NameButton = getglobal("MetaKB_ScrollFrameButton"..iScrollFrameButton.."Name");
		local Info1Button = getglobal("MetaKB_ScrollFrameButton"..iScrollFrameButton.."Info1");
		local Info2Button = getglobal("MetaKB_ScrollFrameButton"..iScrollFrameButton.."Info2");
		local CoordsButton = getglobal("MetaKB_ScrollFrameButton"..iScrollFrameButton.."Coords");

		if(buttonIndex < MetaKB_SearchResults.onePastEnd) then
			if(MetaKB_SearchResults[buttonIndex]["zoneName"] == GetRealZoneText()) then
				-- Unit is in the same zone, show in yellow
				NameButton:SetText(MetaKB_SearchResults[buttonIndex]["name"]);
				Info1Button:SetText(MetaKB_SearchResults[buttonIndex]["desc"]);
				Info2Button:SetText(MetaKB_SearchResults[buttonIndex]["level"]);
				CoordsButton:SetText(MetaKB_SearchResults[buttonIndex]["location"]);
				if(MetaKB_SearchResults[buttonIndex]["cCode"] == 2) then
					CoordsButton:SetTextColor(0,1,0)
				else
					-- Unit is within range, show in green
					CoordsButton:SetTextColor(1,1,0)
				end
				scrollFrameButton:Show();
			else
				if(MetaKB_ShowAllZones or MetaKBOptions.EmbedKB) then
					-- Unit is in a different zone, show in red
					NameButton:SetText(MetaKB_SearchResults[buttonIndex]["name"]);
					Info1Button:SetText(MetaKB_SearchResults[buttonIndex]["desc"]);
					Info2Button:SetText(MetaKB_SearchResults[buttonIndex]["level"]);
					CoordsButton:SetText(MetaKB_SearchResults[buttonIndex]["zoneName"]);
					CoordsButton:SetTextColor(1,0,0)
					scrollFrameButton:Show();
				else
					scrollFrameButton:Hide();
				end
			end
			local ncol = MetaKB_SearchResults[buttonIndex]["ncol"];
			NameButton:SetTextColor(MetaMapNotes_Colors[ncol].r,MetaMapNotes_Colors[ncol].g,MetaMapNotes_Colors[ncol].b)
			Info1Button:SetTextColor(0.8,0.8,0.8)
			Info2Button:SetTextColor(0.5,0.5,0.8)
		else
			scrollFrameButton:Hide();
		end
	end
	FauxScrollFrame_Update(MetaKB_ScrollFrame, MetaKB_SearchResults.onePastEnd - 1,
        METAKB_SCROLL_FRAME_BUTTONS_SHOWN, METAKB_SCROLL_FRAME_BUTTON_HEIGHT)
end

function MetaKB_BuildSearchResults()
	MetaKB_SearchResults = {};
	local nameCount = 0;
	local zoneCount = 0;
	local tempZones = {};
	local currentContinent, currentZone, _, mapName = MetaMap_GetCurrentMapInfo();

	for name, continentTable in MetaKB_Data[MetaKB_dbID] do
		for continent, zoneTable in continentTable do
			for zone in zoneTable do
				local cCode = 1;
				local showAll = false;
				local coordString = "";
				if(continent == currentContinent and mapName == "Kalimdor") then showAll = true; end
				if(continent == currentContinent and mapName == "Eastern Kingdoms") then showAll = true; end
				if(mapName == "World" and continent ~= 0) then showAll = true; end
				if(continent == currentContinent and zone == currentZone or MetaKB_ShowAllZones or showAll) then
					local zoneName = MetaMap_ZoneNames[continent][zone];
					local selectedData = MetaKB_Data[MetaKB_dbID][name][continent][zone];
					local inf1 = selectedData["inf1"];
					local inf2 = selectedData["inf2"];
					local ncol = selectedData["icon"];
					if(ncol == 1) then ncol = 2;
					elseif(ncol == 2) then ncol = 6;
					elseif(ncol == 3) then ncol = 4;
					elseif(ncol == 6) then ncol = 1; end
					if(zoneName ~= GetRealZoneText() or continent == 0) then
						coordString = zoneName;
					else
						coordString, cCode = MetaKB_FormatCoords(selectedData);
					end
					if(string.find(string.lower(name),string.lower(MetaKB_LastSearch),1,true)~=nil
						or string.find(string.lower(inf1),string.lower(MetaKB_LastSearch),1,true)~=nil
						or string.find(string.lower(inf2),string.lower(MetaKB_LastSearch),1,true)~=nil
						or string.find(string.lower(coordString),string.lower(MetaKB_LastSearch),1,true)~=nil) then
						tinsert(MetaKB_SearchResults, {name = name, zoneName = zoneName, desc = inf1, level = inf2, ncol = ncol, location = coordString, cCode = cCode});
						nameCount = nameCount + 1;
						if(tempZones[zoneName] == nil and zoneName ~= nil) then
							zoneCount = zoneCount + 1;
							tempZones[zoneName] = 1;
						end
					end
				end
			end
		end
	end
	MetaKB_ResultFontString:SetText("Found "..nameCount.." NPC/MoBs in "..zoneCount.." zones");
	MetaKB_SearchResults.onePastEnd = nameCount +1;
	MetaKBList_SortBy(MetaMap_sortType, MetaMap_sortDone)
end

function MetaKB_FormatCoords(dataSet, mode)
	local cleanCoords = {};
	local coordString = "";
	for i=1,4 do
		cleanCoords[i] = MetaMap_round(dataSet[i]/100, 0);
	end
	local dx = dataSet[2]/100 - dataSet[4]/100;
	local dy = dataSet[3]/100 - dataSet[1]/100;
	local centerx = dataSet[4]/100 + dx/2;
	local centery = dataSet[1]/100 + dy/2;
	-- truncate to two digits after the decimal again
	centerx = MetaMap_round(centerx, 0);
	centery = MetaMap_round(centery, 0);
	if(mode == nil) then
		if dx >= 3 or dy >= 3 then
		-- if the NPC has a range of 3 map units or greater, show ranges
			coordString = " ("..cleanCoords[4].."-"..cleanCoords[2].."),"..
 	                          " ("..cleanCoords[1].."-"..cleanCoords[3]..")"
		else
			-- otherwise just show an averaged point
			coordString = " ("..centerx..", "..centery..")"
		end
		if(centerx > (MetaKB_PlayerX +3) or centerx < (MetaKB_PlayerX -3) and centery > (MetaKB_PlayerY +3) or centery < (MetaKB_PlayerY -3)) then
			cCode = 1;
		else
			cCode = 2;
		end
		return coordString, cCode;
	elseif(mode == 1) then
		if(centerx == 0 and centery == 0) then
			centerx = 75;
			centery = 95;
		end
		centerx = centerx/100;
		centery = centery/100;
		return centerx, centery, dx, dy;
	end
	return centerx, centery;
end

function MetaKBList_SortBy(aSortType, aSortDone)
	MetaMap_sortType = aSortType;
	MetaMap_sortDone = aSortDone;
  table.sort(MetaKB_SearchResults, MetaMap_SortCriteria);
	if(not MetaMap_sortDone)then
		local count = MetaKB_SearchResults.onePastEnd;
		MetaKB_SearchResults = MetaMap_InvertList(MetaKB_SearchResults);
		MetaKB_SearchResults.onePastEnd = count;
	end
	MetaKB_UpdateScrollFrame();
end

function MetaKB_Search(searchText, suppressErrors)
	if(searchText == nil) then searchText = MetaKB_LastSearch; end
	if(suppressErrors == nil) then suppressErrors = false; end

	MetaKB_LastSearch = searchText;
	if(not MetaKBOptions.EmbedKB) then
		SetMapToCurrentZone();
	end
	MetaKB_PlayerX, MetaKB_PlayerY = GetPlayerMapPosition("player");
	MetaKB_PlayerX = MetaMap_round(MetaKB_PlayerX * 100);
	MetaKB_PlayerY = MetaMap_round(MetaKB_PlayerY * 100);
	FauxScrollFrame_SetOffset(MetaKB_ScrollFrame, 0);
	MetaKB_BuildSearchResults();
	MetaKB_UpdateScrollFrame();
	MetaKB_SearchEditBox:SetText(MetaKB_LastSearch);
end

function MetaKB_ScrollFrameButtonOnClick(button)
	if(button == "LeftButton") then
		MetaKB_ScrollFrameButtonID = this:GetID();
		local x, y = GetCursorPosition();
		x = x / UIParent:GetEffectiveScale();
		y = y / UIParent:GetEffectiveScale();
		MetaKBMenu:SetPoint("TOP", "UIParent", "BOTTOMLEFT", x , y +10);
		MetaKBMenu:Show();
	elseif(button == "RightButton") then
		if(IsControlKeyDown()) then
			MetaKBMenu_CRBSelect(this:GetID());
		elseif(IsShiftKeyDown()) then
			MetaKBMenu_SRBSelect(this:GetID());
		else
			MetaMap_LoadBWP(this:GetID(), 1);
		end
	end
end

function MetaKBMenu_Select(id)
	local name = getglobal("MetaKB_ScrollFrameButton"..MetaKB_ScrollFrameButtonID.."Name"):GetText();
	local zoneName = getglobal("MetaKB_ScrollFrameButton"..MetaKB_ScrollFrameButtonID.."Coords"):GetText();
	if(string.find(zoneName, "%(%d+\.?-?%d*%)?, %(?%d+\.?-?%d*%)")) then
		zoneName = GetRealZoneText();
	end
	local continent, zone = MetaMap_NameToZoneID(zoneName);
	local currentZone = MetaMapNotes_Data[continent][zone];
	local tUpdate = MetaKBOptions.ShowUpdates;

	if(id == 1) then
		MetaKBOptions.ShowUpdates = true;
		PlaySound("MapPing");
		MetaKB_AddMapNotes(name, zoneName, 0);
		MetaMapNotes_MapUpdate();
		PlaySound("igMiniMapClose");
	elseif(id == 2) then
		MetaKBOptions.ShowUpdates = true;
		PlaySound("MapPing");
		MetaKB_AddMapNotes(name, zoneName, 2);
		PlaySound("igMainMenuOption")
	elseif(id == 3) then
		MetaKBOptions.ShowUpdates = true;
		MetaMap_DeleteNotes(METAKB_AUTHOR, name);
	elseif(id == 4) then
		MetaKBOptions.ShowUpdates = true;
		PlaySound("igQuestLogAbandonQuest");
		MetaMap_DeleteNotes(METAKB_AUTHOR);
	elseif(id == 5) then
		MetaKB_Data[MetaKB_dbID][name] = nil;
		PlaySound("Deathbind Sound");
		MetaMap_StatusPrint(format(TEXT(METAKB_REMOVED_FROM_DATABASE), name, zoneName), true);
		MetaKB_Search(MetaKB_LastSearch, true);
	elseif(id == 6) then
			StaticPopupDialogs["Trim_Dbase"] = {
				text = TEXT(METAKB_TRIM_DBASE),
				button1 = TEXT(ACCEPT),
				button2 = TEXT(DECLINE),
				OnAccept = function()
					MetaKB_TrimDatabase();
				end,
				timeout = 60,
				showAlert = 1,
			};
			StaticPopup_Show("Trim_Dbase");
	elseif(id == 7 and ChatFrameEditBox:IsVisible()) then
		local selectedData = MetaKB_Data[MetaKB_dbID][name][continent][zone];
		local centerx, centery = MetaKB_FormatCoords(selectedData, 2)
		local mInfo = " "
		if(selectedData.inf1 ~= "") then mInfo = " ["..selectedData.inf1.."] "; end
		local coordString = centerx..", "..centery;
		ChatFrameEditBox:Insert(name..mInfo.."("..zoneName.." - "..coordString..")");
	elseif(id == 8) then
		local noteID = 0;
		MetaKBMenu:Hide();
		MetaKB_DisplayFrame:GetParent():Hide();
		ShowUIPanel(WorldMapFrame);
		if(continent == 0) then
			MetaMapOptions.MetaMapZone = zone;
			MetaMap_Toggle(true);
		else
			SetMapZoom(continent, zone);
		end
		for index, value in currentZone, 1 do
			if(currentZone[index].name == name) then
				noteID = index;
				break;
			end
		end
		if(noteID == 0 and MetaKBOptions.SetMapShow and not MetaMapFrame:IsVisible()) then
			noteID = MetaMapNotes_GetZoneTableSize(currentZone)+1;
			MetaKB_AddMapNotes(name, zoneName, 0);
			MetaMapNotes_MapUpdate();
		end
		if(noteID > 0) then
			MetaMapPing_SetPing(currentZone, noteID);
		end
	end
	MetaKBOptions.ShowUpdates = tUpdate;
end

function MetaKBMenu_OnUpdate()
	if (MetaKBMenu:IsVisible()) then
		if (not MouseIsOver(MetaKBMenu)) then
			MetaKBMenu:Hide();
		end
	end
end

function MetaKB_TrimDatabase()
	local nameCount = 0;

	for i=1, table.getn(MetaKB_SearchResults) do
		local Name = MetaKB_SearchResults[i].name;
		MetaKB_Data[MetaKB_dbID][Name] = nil;
		nameCount = nameCount + 1
	end
	if(strlen(MetaKB_LastSearch) > 0) then
		MetaMap_StatusPrint("Removed "..nameCount.." entries from database linked to '"..MetaKB_LastSearch.."'", true);
	else
		MetaMap_StatusPrint("Removed ALL entries from database", true);
	end
	MetaKB_Search(MetaKB_LastSearch, true);
end

function MetaKB_AddMapNotes(name, zoneName, mininote)
	if(mininote == nil) then mininote = 0; end
	local continent, zone = MetaMap_NameToZoneID(zoneName);
	local currentZone = MetaKB_Data[MetaKB_dbID][name][continent][zone];
	local coordSets = {
	[1] = { ["n"] = TEXT(METAKB_MAPNOTES_NW_BOUND), ["x"] = 4, ["y"] = 1, },
	[2] = { ["n"] = TEXT(METAKB_MAPNOTES_NE_BOUND), ["x"] = 2, ["y"] = 1, },
	[3] = { ["n"] = TEXT(METAKB_MAPNOTES_SE_BOUND), ["x"] = 2, ["y"] = 3, },
	[4] = { ["n"] = TEXT(METAKB_MAPNOTES_SW_BOUND), ["x"] = 4, ["y"] = 3, }, };
	local infoOne = currentZone["inf1"];
	local infoTwo = currentZone["inf2"];
	local icon = currentZone["icon"];
	local namecol = icon;
	if(icon == 1) then namecol = 2;
	elseif(icon == 2) then namecol = 6;
	elseif(icon == 3) then namecol = 4;
	elseif(icon == 6) then namecol = 1; end
	local centerx, centery, dx, dy = MetaKB_FormatCoords(currentZone, 1)
	local noteAdded, nearNote = MetaMapNotes_AddNewNote(continent, zone, centerx, centery, name, infoOne, infoTwo, METAKB_AUTHOR, icon, namecol, 9, 6, mininote);
	if(noteAdded) then
		if(mininote ~= 2) then
			MetaMap_StatusPrint(format(METAMAPNOTES_ACCEPT_NOTE, MetaMap_ZoneNames[continent][zone]), MetaKBOptions.ShowUpdates);
		end
	else
		MetaMap_StatusPrint(format(METAMAPNOTES_DECLINE_NOTE, MetaMapNotes_Data[continent][zone][nearNote].name, MetaMap_ZoneNames[continent][zone]), MetaKBOptions.ShowUpdates);
	end
	if(mininote > 0) then
		MetaMap_StatusPrint(format(METAMAPNOTES_ACCEPT_MININOTE, GetRealZoneText()), true);
	end
	if(noteAdded and mininote == 0 and (dx >= 3 or dy >= 3) and MetaKBOptions.CreateMapNotesBoundingBox) then
		local x2 = currentZone[coordSets[4].x]/10000
		local y2 = currentZone[coordSets[4].y]/10000
		local skipNext = false
		for i in coordSets do
			local x1 = currentZone[coordSets[i].x]/10000
			local y1 = currentZone[coordSets[i].y]/10000
			local noteAdded = MetaMapNotes_AddNewNote(continent, zone, x1, y1, name, infoOne, infoTwo, METAKB_AUTHOR, 10, namecol, 9, 6);
			if(noteAdded) then
				if(not skipNext) then
					MetaMapNotes_ToggleLine(continent, zone, x2, y2, x1, y1);
					MetaMapNotes_ToggleLine(continent, zone, centerx, centery, x1, y1);
				end
				skipNext = false;
			else
				skipNext = true;
			end
			x2,y2 = x1,y1;
		end
	end
end

function MetaKB_ToggleAllZones()
	MetaKB_ShowAllZones = not MetaKB_ShowAllZones;
	if MetaKB_ShowAllZones then
		this:SetText(METAKB_SHOW_LOCALZONE);
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		this:SetText(METAKB_SHOW_ALLZONES);
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
	MetaKB_Search();
end

function MetaKB_ToggleAutoTrack()
	MetaKBOptions.AutoTrack = not MetaKBOptions.AutoTrack;
	if(MetaKBOptions.AutoTrack) then
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
end

function MetaKB_ToggleShowUpdates()
	MetaKBOptions.ShowUpdates = not MetaKBOptions.ShowUpdates
	if MetaKBOptions.ShowUpdates then
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
end

function MetaKB_ToggleDbase()
	MetaKBOptions.KBstate = not MetaKBOptions.KBstate;
	if MetaKBOptions.KBstate then
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
end

function MetaKB_ToggleSetNote()
	MetaKBOptions.NewTargetNote = not MetaKBOptions.NewTargetNote
	if MetaKBOptions.NewTargetNote then
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
end

function MetaKB_ToggleBoundingBox()
	MetaKBOptions.CreateMapNotesBoundingBox = not MetaKBOptions.CreateMapNotesBoundingBox;
	if MetaKBOptions.CreateMapNotesBoundingBox then
		PlaySound("igMainMenuOptionCheckBoxOn");
	else
		PlaySound("igMainMenuOptionCheckBoxOff");
	end
end

