--[[

	SKMap Lua file
]]

-- Configuration variables

-- Local variables
-- any variables declared local will not be available for use outside this module

SKM_VERSION = "1.6";
SKM_LOADED_MSG = "SKMap "..SKM_VERSION.." AddOn loaded"

SKM_TITLE = "SKMap "..SKM_VERSION;



StaticPopupDialogs["SKMAP_CONFIRM"] = {
	button1 = TEXT(OKAY),
	button2 = TEXT(CANCEL),
	OnShow = nil,
	OnAccept = nil,
	OnCancel = function() SKMap_DeleteButton_Cancel() end,
	hasMoneyFrame = nil,
	showAlert = 1,
	exclusive = 1,
	whileDead = 1,
	interruptCinematic = 1,
	timeout = 0
};


-- complete list of recorded global settings
SKM_OPTION_LIST = {
	"ShowTargetInfo",
	"SmallTargetInfo",
	"WarSoundWarning",
	"WarFloatingMessage",
	"WarAutoTarget",
	"RecordPlayerKill",
	"RecordCreatureKill",
	"RecordPlayerDeath",
	"DisplayKillRecord",
	"DisplayCreatureKillRecord",
	"DisplayDeathRecord",
	"MapDisplayRecords",
	"CreatureKillRecordsByZone",
	"IgnoreLowerEnemies",
	"IgnoreLevelThreshold",
	"ShowTargetGuildInfo",
	"ShowTargetClassInfo",
	"ShowWorldMapControl",
	"ShowMinimapButton",
	"MinimapButtonPosition",
	"MinimapButtonOffset",
	"IgnoreNoPvPFlag",
	"StoreEnemyPlayers",
	"StoreDuels",
	"AssistKillStat",
	"LockedTargetInfo",
	"TooltipTargetInfo",
	"WarEnableFilter",
	"WarFilterDelay",
	"WarChatMessage",
	"WarShowNote",
	"DataCleanUp",
	"DataCleanUpInterval",
	"CleanInactiveEnemies",
	"CleanInactiveEnemiesDelay",
	"SharedWarMode",
	"TooltipPlayerNote",
	"EnemyListAutoUpdate",
	"EnemyListAutoUpdateDelay",
	"CleanEmptyGuilds",
	"RecordPlayerDeathNonPvP",
	"ReportPlayerDeath",
	"EnemyList_SortType",
	"EnemyList_SortTypes",
	"EnemyList_ReverseSort",
	"GuildList_SortType",
	"GuildList_SortTypes",
	"GuildList_ReverseSort",
	"DuelList_SortType",
	"DuelList_SortTypes",
	"DuelList_ReverseSort"
};




SKM_MAX_CREEP_RECORD_BY_ZONE = 100;


local SKM_TAB_SUBFRAMES = { "SKMap_ListFrame", "SKMap_DuelFrame", "SKMap_ReportFrame", "SKMap_OptionsFrame" };

local SKM_OptionsFrameCheckButtons = {
	[1]  = { Option = "ShowTargetInfo", Text = SKM_UI_STRINGS.Options_Check_ShowTargetInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ShowTargetInfo };
	[2]  = { Option = "SmallTargetInfo", Text = SKM_UI_STRINGS.Options_Button_SmallTargetInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_SmallTargetInfo };
	[3]  = { Option = "MapDisplayRecords", Text = SKM_UI_STRINGS.Options_Button_MapDisplayRecords, Tooltip = SKM_UI_STRINGS.Options_Tooltip_MapDisplayRecords };
	[4]  = { Option = "WarSoundWarning", Text = SKM_UI_STRINGS.Options_Button_WarSoundWarning, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarSoundWarning };
	[5]  = { Option = "WarFloatingMessage", Text = SKM_UI_STRINGS.Options_Button_WarFloatingMessage, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarFloatingMessage };
	[6]  = { Option = "WarAutoTarget", Text = SKM_UI_STRINGS.Options_Button_WarAutoTarget, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarAutoTarget };
	[7]  = { Option = "RecordPlayerDeath", Text = SKM_UI_STRINGS.Options_Button_RecordPlayerDeath, Tooltip = SKM_UI_STRINGS.Options_Tooltip_RecordPlayerDeath };
	[8]  = { Option = "DisplayDeathRecord", Text = SKM_UI_STRINGS.Options_Button_DisplayDeathRecord, Tooltip = SKM_UI_STRINGS.Options_Tooltip_DisplayDeathRecord };
	[9]  = { Option = "RecordPlayerKill", Text = SKM_UI_STRINGS.Options_Button_RecordPlayerKill, Tooltip = SKM_UI_STRINGS.Options_Tooltip_RecordPlayerKill };
	[10] = { Option = "DisplayKillRecord", Text = SKM_UI_STRINGS.Options_Button_DisplayKillRecord, Tooltip = SKM_UI_STRINGS.Options_Tooltip_DisplayKillRecord };
	[11] = { Option = "RecordCreatureKill", Text = SKM_UI_STRINGS.Options_Button_RecordCreatureKill, Tooltip = SKM_UI_STRINGS.Options_Tooltip_RecordCreatureKill };
	[12] = { Option = "DisplayCreatureKillRecord", Text = SKM_UI_STRINGS.Options_Button_DisplayCreatureKillRecord, Tooltip = SKM_UI_STRINGS.Options_Tooltip_DisplayCreatureKillRecord };
	[13] = { Option = "IgnoreLowerEnemies", Text = SKM_UI_STRINGS.Options_Button_IgnoreLowerEnemies, Tooltip = SKM_UI_STRINGS.Options_Tooltip_IgnoreLowerEnemies };
	[14] = { Option = "ShowTargetGuildInfo", Text = SKM_UI_STRINGS.Options_Button_ShowTargetGuildInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ShowTargetGuildInfo };
	[15] = { Option = "ShowWorldMapControl", Text = SKM_UI_STRINGS.Options_Button_ShowWorldMapControl, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ShowWorldMapControl };
	[16] = { Option = "ShowTargetClassInfo", Text = SKM_UI_STRINGS.Options_Button_ShowTargetClassInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ShowTargetClassInfo };
	[17] = { Option = "ShowMinimapButton", Text = SKM_UI_STRINGS.Options_Button_ShowMinimapButton, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ShowMinimapButton };
	[18] = { Option = "IgnoreNoPvPFlag", Text = SKM_UI_STRINGS.Options_Button_IgnoreNoPvPFlag, Tooltip = SKM_UI_STRINGS.Options_Tooltip_IgnoreNoPvPFlag };
	[19] = { Option = "StoreEnemyPlayers", Text = SKM_UI_STRINGS.Options_Button_StoreEnemyPlayers, Tooltip = SKM_UI_STRINGS.Options_Tooltip_StoreEnemyPlayers };
	[20] = { Option = "StoreDuels", Text = SKM_UI_STRINGS.Options_Button_StoreDuels, Tooltip = SKM_UI_STRINGS.Options_Tooltip_StoreDuels };
	[21] = { Option = "LockedTargetInfo", Text = SKM_UI_STRINGS.Options_Button_LockedTargetInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_LockedTargetInfo };
	[22] = { Option = "TooltipTargetInfo", Text = SKM_UI_STRINGS.Options_Button_TooltipTargetInfo, Tooltip = SKM_UI_STRINGS.Options_Tooltip_TooltipTargetInfo };
	[23] = { Option = "WarEnableFilter", Text = SKM_UI_STRINGS.Options_Button_WarEnableFilter, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarEnableFilter };
	[24] = { Option = "WarChatMessage", Text = SKM_UI_STRINGS.Options_Button_WarChatMessage, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarChatMessage };
	[25] = { Option = "WarShowNote", Text = SKM_UI_STRINGS.Options_Button_WarShowNote, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarShowNote };
	[26] = { Option = "DataCleanUp", Text = SKM_UI_STRINGS.Options_Button_DataCleanUp, Tooltip = SKM_UI_STRINGS.Options_Tooltip_DataCleanUp };
	[27] = { Option = "CleanInactiveEnemies", Text = SKM_UI_STRINGS.Options_Button_CleanInactiveEnemies, Tooltip = SKM_UI_STRINGS.Options_Tooltip_CleanInactiveEnemies };
	[28] = { Option = "SharedWarMode", Text = SKM_UI_STRINGS.Options_Button_SharedWarMode, Tooltip = SKM_UI_STRINGS.Options_Tooltip_SharedWarMode };
	[29] = { Option = "TooltipPlayerNote", Text = SKM_UI_STRINGS.Options_Button_TooltipPlayerNote, Tooltip = SKM_UI_STRINGS.Options_Tooltip_TooltipPlayerNote };
	[30] = { Option = "EnemyListAutoUpdate", Text = SKM_UI_STRINGS.Options_Button_EnemyListAutoUpdate, Tooltip = SKM_UI_STRINGS.Options_Tooltip_EnemyListAutoUpdate };
	[31] = { Option = "CleanEmptyGuilds", Text = SKM_UI_STRINGS.Options_Button_CleanEmptyGuilds, Tooltip = SKM_UI_STRINGS.Options_Tooltip_CleanEmptyGuilds };
	[32] = { Option = "RecordPlayerDeathNonPvP", Text = SKM_UI_STRINGS.Options_Button_RecordPlayerDeathNonPvP, Tooltip = SKM_UI_STRINGS.Options_Tooltip_RecordPlayerDeathNonPvP };
	[33] = { Option = "ReportPlayerDeath", Text = SKM_UI_STRINGS.Options_Button_ReportPlayerDeath, Tooltip = SKM_UI_STRINGS.Options_Tooltip_ReportPlayerDeath };

};

local SKM_OptionsFrameSliders = {
	[1] = { Option = "CreatureKillRecordsByZone", valueStep = 1, minValue = 0, maxValue = SKM_MAX_CREEP_RECORD_BY_ZONE, Text = SKM_UI_STRINGS.Options_Slider_CreatureKillRecordsByZone, Tooltip = SKM_UI_STRINGS.Options_Tooltip_CreatureKillRecordsByZone };
	[2] = { Option = "IgnoreLevelThreshold", valueStep = 1, minValue = 0, maxValue = 100, Text = SKM_UI_STRINGS.Options_Slider_IgnoreLevelThreshold, Tooltip = SKM_UI_STRINGS.Options_Tooltip_IgnoreLevelThreshold };
	[3] = { Option = "MinimapButtonPosition", valueStep = 1, minValue = 0, maxValue = 100, Text = SKM_UI_STRINGS.Options_Slider_MinimapButtonPosition, Tooltip = SKM_UI_STRINGS.Options_Tooltip_MinimapButtonPosition };
	[4] = { Option = "MinimapButtonOffset", valueStep = 1, minValue = 50, maxValue = 120, Text = SKM_UI_STRINGS.Options_Slider_MinimapButtonOffset, Tooltip = SKM_UI_STRINGS.Options_Tooltip_MinimapButtonOffset };
	[5] = { Option = "WarFilterDelay", valueStep = 1, minValue = 1, maxValue = 60, Text = SKM_UI_STRINGS.Options_Slider_WarFilterDelay, Tooltip = SKM_UI_STRINGS.Options_Tooltip_WarFilterDelay };
	[6] = { Option = "DataCleanUpInterval", valueStep = 1, minValue = 1, maxValue = 100, Text = SKM_UI_STRINGS.Options_Slider_DataCleanUpInterval, Tooltip = SKM_UI_STRINGS.Options_Tooltip_DataCleanUpInterval };
	[7] = { Option = "CleanInactiveEnemiesDelay", valueStep = 1, minValue = 1, maxValue = 150, Text = SKM_UI_STRINGS.Options_Slider_CleanInactiveEnemiesDelay, Tooltip = SKM_UI_STRINGS.Options_Tooltip_CleanInactiveEnemiesDelay };
	[8] = { Option = "EnemyListAutoUpdateDelay", valueStep = 1, minValue = 0, maxValue = 300, Text = SKM_UI_STRINGS.Options_Slider_EnemyListAutoUpdateDelay, Tooltip = SKM_UI_STRINGS.Options_Tooltip_EnemyListAutoUpdateDelay };

};

local SKM_OptionFrameLabels = {
	[1] = { Text = SKM_UI_STRINGS.Options_Label_General };
	[2] = { Text = SKM_UI_STRINGS.Options_Label_Map };
	[3] = { Text = SKM_UI_STRINGS.Options_Label_War };
	[4] = { Text = SKM_UI_STRINGS.Options_Label_Record };
	[5] = { Text = SKM_UI_STRINGS.Options_Label_Minimap };
	[6] = { Text = SKM_UI_STRINGS.Options_Label_Cleanup };
};


-- new option management
SKM_OptionsList = {
	[1] = {
		Title = SKM_OptionFrameLabels[1];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[1];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[19];
				};
			};
			[2] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[21];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[18];
				};
			};
			[3] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[2];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[13];
				};
			};
			[4] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[16];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 40;
					Value = SKM_OptionsFrameSliders[2];
				};
			};
			[5] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[14];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[20];
				};
			};
			[6] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[22];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[30];
				};
			};
			[7] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[29];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[8];
				};
			};
			[8] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[33];
				};
				Right = nil;	
			};
		};
	};

	[2] = {
		Title = SKM_OptionFrameLabels[2];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[3];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[15];
				};
			};
		};
	};

	[3] = {
		Title = SKM_OptionFrameLabels[3];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[4];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[23];
				};
			};
			[2] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[5];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[5];
				};
			};
			[3] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[24];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[6];
				};
			};
			[4] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[25];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[28];
				};
			};

		};
	};

	[4] = {
		Title = SKM_OptionFrameLabels[4];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[7];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[11];
				};
			};
			[2] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[32];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[1];
				};
			};
			[3] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[8];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[12];
				};
			};
			[4] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[9];
				};
			};
			[5] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[10];
				};
			};
		};
	};

	[5] = {
		Title = SKM_OptionFrameLabels[5];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[17];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[3];
				};
			};
			[2] = {
				Right = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[4];
				};
			};
		};
	};

	[6] = {
		Title = SKM_OptionFrameLabels[6];
		Lines = {
			[1] = {
				Left = {
					Type = _SKM._checkButton;
					Offset = 20;
					Value = SKM_OptionsFrameCheckButtons[26];
				};
				Right = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[27];
				};
			};
			[2] = {
				Left = {
					Type = _SKM._slider;
					Offset = 30;
					Value = SKM_OptionsFrameSliders[6];
				};
				Right = {
					Type = _SKM._slider;
					Offset = 40;
					Value = SKM_OptionsFrameSliders[7];
				};
			};
			[3] = {
				Left = nil;
				Right = {
					Type = _SKM._checkButton;
					Offset = 30;
					Value = SKM_OptionsFrameCheckButtons[31];
				};
			};
		};
	};

}

SKM_List_Options = { };


SKM_LISTFRAME_ROWS = 13;
SKM_LISTFRAME_ROWHEIGHT = 16;

SKM_DUELFRAME_ROWS = 13;
SKM_DUELFRAME_ROWHEIGHT = 16;

SKM_OPTIONFRAME_ROWS = 11;
SKM_OPTIONFRAME_ROWHEIGHT = 30;

-- lists contents
SKM_List_Content = { };
SKM_GuildList_Content = { };
SKM_DuelList_Content = { };

-- enemy list sort options
--SKM_List_SortType = "Name";
--SKM_List_SortTypes = { SKM_List_SortType };
--SKM_List_ReverseSort = false;

-- guild list sort options
--SKM_GuildList_SortType = "Name";
--SKM_GuildList_SortTypes = { SKM_GuildList_SortType };
--SKM_GuildList_ReverseSort = false;

-- duel list sort options
--SKM_DuelList_SortType = "Name";
--SKM_DuelList_SortTypes = { SKM_DuelList_SortType };
--SKM_DuelList_ReverseSort = false;

-- which of the two lists is currently active
SKM_List_ActiveList = _SKM._players;

-- remember the selected player or guild from the lists
SKM_List_SelectedPlayer = nil;
SKM_List_SelectedGuild = nil;

SKM_EditNoteContext = { List = nil, Element = nil };

SKM_LISTFRAME_DETAIL_ROWS = 8;
SKM_DUELFRAME_DETAIL_ROWS = 8;

SKM_BOOKFRAME_ROWS = 20;
SKM_BOOKFRAME_COLUMNS = 4;

SKM_BookPages = { };
SKM_BookCurPage = nil;
SKM_CurrentBook = nil;

SKM_BOOK_SEPARATOR = "_________________________________________________________________";


SKM_ActivePopup = false;



local SKMap_Original_ChatFrame_OnEvent;


--Stolen from TextFilter.lua
function SKMap_FilterChatEvent(event)
	chatEvents = {
		--possible filtered events
		"CHAT_MSG_SAY",
		"CHAT_MSG_YELL",
		"CHAT_MSG_PARTY",
		"CHAT_MSG_RAID",
		"CHAT_MSG_WHISPER",
		"CHAT_MSG_WHISPER_INFORM",
		"CHAT_MSG_EMOTE",
		"CHAT_MSG_TEXT_EMOTE",
		"CHAT_MSG_GUILD",
		"CHAT_MSG_OFFICER",
		"GUILD_MOTD",
		"CHAT_MSG_CHANNEL",
		"CHAT_MSG_SYSTEM",
	};
	for key,value in chatEvents do
		if(event == value) then
			return true;
		end
	end
	return false;
end


function SKMap_ChatFrame_OnEvent(event)
	SKMap_Original_ChatFrame_OnEvent(event); -- call the real ChatFrame_OnEvent function

	--if we haven't already done so, hook the AddMessage function
	if (not this.SKMap_ChatColor_Original_AddMessage) then
		this.SKMap_ChatColor_Original_AddMessage = this.AddMessage;
		this.AddMessage = SKMap_ChatColor_AddMessage;
	end
end


-- test
SKM_Karma = {
	["Tanae"] = { [_SKM._name] = "Tanae" };
	--["Lumen"] = { [_SKM._name] = "Lumen" };
	["Tyronia"] = { [_SKM._name] = "Tyronia" };
};


function SKMap_KarmaNameColor(sMsg)
	local sNewMsg = sMsg;
	local idx, val;
	for idx, val in SKM_Karma do
		local sName = val[_SKM._name];
		local red=255;
		local green=0;
		local blue=0;
		local sRep = string.format("|c00%02x%02x%02x%s|r", red, green, blue, sName);
		sNewMsg = string.gsub(sNewMsg, sName, sRep);
	end
	return sNewMsg;
end


function SKMap_ChatColor_AddMessage(this, msg, r, g, b, id)
	local FName = "SKMap_ChatColor_AddMessage";

	local sNewMsg = msg;

	if (SKMap_FilterChatEvent(event)) then
		--hmm, don't use SkM_Trace here or this would generate an infinite loop and a stack overflow :)
		--SkM_Trace(FName, 1, "r="..snil(r)..", g="..snil(g)..", b="..snil(b)..", msg="..snil(msg));
		--UIErrorsFrame:AddMessage("r="..snil(r)..", g="..snil(g)..", b="..snil(b)..", msg="..snil(msg), 1.0, 1.0, 1.0, 1.0, UIERRORS_HOLD_TIME);

		for sStart, sPlayer, sEnd in string.gfind(msg, "(.*)|Hplayer:(.+)%[(.+)") do
			sNewMsg = sStart.."|Hplayer:"..sPlayer.."["..SKMap_KarmaNameColor(sEnd);
			this:SKMap_ChatColor_Original_AddMessage(sNewMsg, r, g, b, id);
			return;
		end

		-- pattern "|Hplayer:"... not found, so just replace in whole message
		sNewMsg = SKMap_KarmaNameColor(sNewMsg);
	end

	this:SKMap_ChatColor_Original_AddMessage(sNewMsg, r, g, b, id);
end



-- --------------------------------------------------------------------------------------
-- SKMap_OnLoad
-- --------------------------------------------------------------------------------------
-- Global OnLoad event for the loading frame.
-- Declare slash handlers.
-- Register all events we need.
-- Initialize module.
-- --------------------------------------------------------------------------------------
function SKMap_OnLoad()

	SlashCmdList["SKMAPCOMMAND"] = SKMap_SlashHandler;
	SLASH_SKMAPCOMMAND1 = "/skm";
	--SLASH_SKMAPCOMMAND2 = nil;


	-- Hook ChatFrame_OnEvent so we can hook AddMessage
	--SKMap_Original_ChatFrame_OnEvent = ChatFrame_OnEvent;
	--ChatFrame_OnEvent = SKMap_ChatFrame_OnEvent;


-- to respond to events (in OnEvent) you must first register to receive them
-- with this:RegisterEvent("EVENT_NAME").  A list of events can be found
-- at the cosmos site.  You can get to it directly by going through WoWWiki.com

-- If we've saved config variables, we'll almost always want to respond to
-- the variables loaded event.  Prior to this, the saved variables are NOT in
-- memory, don't try to use them.
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UNIT_NAME_UPDATE");
	this:RegisterEvent("PLAYER_TARGET_CHANGED");
	this:RegisterEvent("UPDATE_MOUSEOVER_UNIT");
	this:RegisterEvent("UNIT_HEALTH");
	this:RegisterEvent("PLAYER_DEAD");
	this:RegisterEvent("PLAYER_ALIVE");
	this:RegisterEvent("PLAYER_LEVEL_UP");
	this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF");
	this:RegisterEvent("WORLD_MAP_UPDATE");
	this:RegisterEvent("CLOSE_WORLD_MAP");
	this:RegisterEvent("PARTY_MEMBERS_CHANGED");
	this:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS");
	this:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE");
	this:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS");
	this:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE");
	this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS");
	this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE");
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE");
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE");
	this:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS");
	this:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE");
	this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS");
	this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE");
	this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH");
	this:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN");
	this:RegisterEvent("CHAT_MSG_COMBAT_HONOR_GAIN");

	this:RegisterEvent("DUEL_FINISHED");
	this:RegisterEvent("DUEL_REQUESTED");	-- does not seem to be triggered at all !!
	this:RegisterEvent("CHAT_MSG_SYSTEM");



	--this:RegisterEvent("CHAT_MSG_CHANNEL");
	--this:RegisterEvent("GUILD_ROSTER_UPDATE");
	--this:RegisterEvent("GUILD_ROSTER_SHOW");
	--this:RegisterEvent("PLAYER_GUILD_UPDATE");


	-- to catch the ESC key
	tinsert(UISpecialFrames,"SKMapFrame");

	if ( DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage(SKM_LOADED_MSG);
	end

	-- module initializations
	SkM_Initialize();

	--UIErrorsFrame:AddMessage(SKM_LOADED_MSG, 1.0, 1.0, 1.0, 1.0, UIERRORS_HOLD_TIME);
end


-- --------------------------------------------------------------------------------------
-- SKMap_OnEvent
-- --------------------------------------------------------------------------------------
-- Global OnEvent events caught by the loading frame
-- --------------------------------------------------------------------------------------
function SKMap_OnEvent()
	local FName = "SKMap_OnEvent";

	-- whatever the event is, check that data has been initialized
	-- (this doesn't do anything if it's the case)
	SkM_InitData(false);

	--SkM_Trace(FName, 0, event.." : arg1 = "..snil(arg1));

	-- This is called when one of the events we registered for actually fires
	-- the specific event is in the variable event
	if (event == "VARIABLES_LOADED") then

		if( DEFAULT_CHAT_FRAME ) then
			--DEFAULT_CHAT_FRAME:AddMessage("SKMap variables loaded");
		end

		SkM_Initialize();
		SkM_DataCleanUp();
		SkM_DataFixMapIndexes();
		SkM_DataModelMigration();
		SkM_MapShiftMigration();

		-- if the option has not been set at all yet, don't touch minimap icon
		if (SkM_GetOption("ShowMinimapButton") ~= nil) then
			SKMap_SetMiniMapIcon();
		end


	elseif (event == "UNIT_NAME_UPDATE") then

		-- ok, character has been loaded, here we can query his level !
		if (arg1 == SKM_UNIT_PLAYER) then
			SKM_Context.PlayerLevel = UnitLevel(SKM_UNIT_PLAYER);
		end

	elseif (event == "WORLD_MAP_UPDATE") then
		SkM_WorldMapUpdate();

	elseif ( event == "CLOSE_WORLD_MAP" ) then
		SkM_CloseWorldMap();

	elseif ( event == "PARTY_MEMBERS_CHANGED" ) then
		SkM_BuildGroupList();

	elseif ( event == "PLAYER_TARGET_CHANGED" ) then
		SkM_UpdateUnitData();
		SkM_SetTargetInfo();

	elseif ( event == "UPDATE_MOUSEOVER_UNIT" ) then
		SkM_MouseOverUnit();

	elseif (event == "UNIT_HEALTH") then
		if (arg1 == SKM_UNIT_TARGET) then
			SkM_TargetHealthUpdated();
		end

	elseif (event == "CHAT_MSG_COMBAT_XP_GAIN") then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_XpGain(arg1);

	elseif (event == "PLAYER_DEAD") then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_PlayerDeath();

	elseif (event == "PLAYER_ALIVE") then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_PlayerAlive();

	elseif (event == "PLAYER_LEVEL_UP") then
		SkM_PlayerLevelUp();

	elseif (event == "CHAT_MSG_COMBAT_HOSTILE_DEATH") then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_HostileDeath(arg1);

	elseif (	event == "CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS" -- friend hits an enemy
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_FriendCombatHit(arg1);

	elseif (	event == "CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE" -- friend damages an enemy with a spell
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_FriendCombatSpell(arg1);

	elseif (	event == "CHAT_MSG_COMBAT_SELF_HITS" -- player hits an enemy
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_SelfCombatHit(arg1);

	elseif ( 	event == "CHAT_MSG_SPELL_SELF_DAMAGE" -- player damages an enemy with a spell
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_SelfCombatSpell(arg1);

	elseif (	event == "CHAT_MSG_COMBAT_PET_HITS"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_PetCombatHit(arg1);

	elseif ( 	event == "CHAT_MSG_SPELL_PET_DAMAGE"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_PetCombatSpell(arg1);

	elseif (	event == "CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_EnemyCombatHit(arg1);

	elseif ( 	event == "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_EnemyCombatSpell(arg1);

	elseif (	event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_CreatureCombatHit(arg1);

	elseif ( 	event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_CreatureCombatSpell(arg1);

	elseif (	event == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_EnemyDot(arg1);

	elseif (	event == "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE"
	) then
		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseCombatChat_SelfDot(arg1);

	elseif ( event == "CHAT_MSG_SYSTEM") then
		--SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_ParseDuelResult(arg1);

--	elseif (	event == "DUEL_FINISHED" or event == "DUEL_REQUESTED" or event == "DUEL_INBOUNDS" or event == "DUEL_OUTOFBOUNDS"
--		        or event == "CHAT_MSG" or event == "CHAT_MSG_SYSTEM"
--
--	) then
--		SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
--

	elseif (	event == "CHAT_MSG_COMBAT_HONOR_GAIN") then
		SkM_Trace(FName, 0, event.." : arg1 = "..snil(arg1));

		SkM_ParseCombatChat_HonorKill(arg1);


	elseif (event == "GUILD_ROSTER_SHOW" or event == "GUILD_ROSTER_UPDATE" or event == "PLAYER_GUILD_UPDATE") then
	  SkM_Trace(FName, 1, event.." : arg1 = "..snil(arg1));
		SkM_BuildGuildList();

	else
		SkM_Trace(FName, 1, "Non handled event : "..event..", arg1 = "..snil(arg1));
	end

end


function SKMap_MiniMapIcon(frame, pPos, pRadius)
	frame:ClearAllPoints();
	frame:SetFrameLevel(Minimap:GetFrameLevel() + 10);
	frame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", 52 - (pRadius * cos(pPos)), (pRadius * sin(pPos)) - 52);
end


function SKMap_MoveMiniMapIcon(iValue, iOffsetValue)
	local iPosition;

	if (not iValue) or (not iOffsetValue) then
		return;
	end

	iPosition = math.floor( (iValue / 100) * (377 - 256) ) + 256;

	--SKMap_MiniMapIcon(SKMapMinimapButton, iPosition, SKM_Config.MinimapButtonOffset);
	SKMap_MiniMapIcon(SKMapMinimapButton, iPosition, iOffsetValue);
end


function SKMap_SetMiniMapIcon(iPosition, iOffset)
	if (not SkM_GetOption("ShowMinimapButton")) then
		SKMapMinimapButton:Hide();
	else
		SKMapMinimapButton:Show();
		local iValue, iOffsetValue;
		if (iPosition) then
			iValue = iPosition;
		else
			iValue = SkM_GetOption("MinimapButtonPosition");
		end
		if (iOffset) then
			iOffsetValue = iOffset;
		else
			iOffsetValue = SkM_GetOption("MinimapButtonOffset");
		end
		SKMap_MoveMiniMapIcon(iValue, iOffsetValue);
	end
end


function SKMap_WorldMapPOI_OnEnter(id)
	local FName = "SKMap_OnEnter";

	SkM_InitData(false);
	SkM_WorldMapEnterPOI(id);
end

function SKMap_WorldMapPOI_OnLeave(id)
	local FName = "SKMap_OnLeave";

	SkM_InitData(false);
	SkM_WorldMapLeavePOI(id);
end



function SKMap_SlashHandler(msg)
	-- This function is called when a user types one of your slash commands
	-- the text they enter after the command comes in msg

	SkM_InitData(false);

	if ( ( not msg) or ( strlen(msg) <= 0 ) ) then
		SKMap_ToggleUI();
		return;
	end

	--UIErrorsFrame:AddMessage(msg, 1.0, 1.0, 1.0, 1.0, UIERRORS_HOLD_TIME);


	local sCmd, sParams = SkM_ExtractParam(msg);
	local sParamStr = sParams;

	if ( (sCmd) and (string.len(sCmd) > 0) ) then
		sCmd = string.lower(sCmd);
	else
		sCmd = "";
	end

	local iNbParam = 0;
	local sParam = {};
	while (sParams ~= "") do
		iNbParam = iNbParam + 1;
		sParam[iNbParam], sParams = SkM_ExtractParam(sParams);
	end

	if (SkM_IdentifyCommand(sCmd, "debug")) then
		local iLevel = -1;
		if (iNbParam == 0) then
			SkM_SetDebugLevel(iLevel);
		else

			if (sParam[1] == "startrec") then
				SkM_StartDebugRecord();
			elseif (sParam[1] == "stoprec") then
				SkM_StopDebugRecord();
			elseif (sParam[1] == "clearrec") then
				SkM_ClearDebugRecord();

			else
				if (sParam[1] ~= "off") then
					iLevel = tonumber(sParam[1]);
				end
				SkM_SetDebugLevel(iLevel);
			end

		end


	elseif (SkM_IdentifyCommand(sCmd, "war")) then
		if (iNbParam == 1) then
			local sName = sParam[1];
			SkM_UnknownEnemyWar(sName, true, true);
		else
			SkM_ChatMessageCol("Usage : /skm war <player name>");
		end

	elseif (SkM_IdentifyCommand(sCmd, "peace")) then
		if (iNbParam == 1) then
			local sName = sParam[1];
			SkM_UnknownEnemyWar(sName, false, true);
		else
			SkM_ChatMessageCol("Usage : /skm peace <player name>");
		end

	elseif (SkM_IdentifyCommand(sCmd, "swar")) then
		if (iNbParam == 0) then
			SkM_ShowUnknownEnemyWar();
		else
			SkM_ChatMessageCol("Usage : /skm swar");
		end

	elseif (SkM_IdentifyCommand(sCmd, "cwar")) then
		if (iNbParam == 0) then
			SkM_ClearUnknownEnemyWar();
		else
			SkM_ChatMessageCol("Usage : /skm cwar");
		end

	elseif (SkM_IdentifyCommand(sCmd, "inf")) then
		if (iNbParam >= 1) and (iNbParam <= 3) then
			local sName = sParam[1];
			local bMatchFullName = false;
			local bMatchSpecialChar = false;
			if (iNbParam >= 2) then
				if (sParam[2] == "1") then
					bMatchFullName = true;
				end
			end
			if (iNbParam >= 3) then
				if (sParam[3] == "1") then
					bMatchSpecialChar = true;
				end
			end
			SkM_GetEnemyInfo(sName, bMatchFullName, bMatchSpecialChar);
		else
			SkM_ChatMessageCol("Usage : /skm inf <player name> [<full name match> [<special char match>]]");
		end

	else
		SkM_ChatMessageCol("Unknown command");
	end

end


function SKMap_ToggleUI(tab)
	local FName = "SKMap_ToggleUI";
	SkM_InitData(false);

	if (not SKMapFrame) then
		SkM_ChatMessageCol("Error : SKMapFrame not loaded");
		return;
	end

	if (not tab) then
		if (SKMapFrame:IsVisible()) then
			HideUIPanel(SKMapFrame);
			--SKMapFrame:Hide();
		else
			ShowUIPanel(SKMapFrame);
			--SKMapFrame:Show();

			local selectedFrameName = SKM_TAB_SUBFRAMES[SKMapFrame.selectedTab];
			SkM_Trace(FName, 1, "Selected frame name = "..snil(selectedFrameName));

			local selectedFrame = getglobal(selectedFrameName);

-- NCHNCH : the following line sometimes generates error because selectedFrame is nil !!!
-- then it's required to ReloadUI();
-- see if there's a solution !
			if ( not selectedFrame:IsVisible() ) then
				selectedFrame:Show()
			end
		end
	else

		local subFrame = getglobal(tab);
		if ( subFrame ) then
			PanelTemplates_SetTab(SKMapFrame, subFrame:GetID());
			if ( SKMapFrame:IsVisible() ) then
				if ( subFrame:IsVisible() ) then
					HideUIPanel(SKMapFrame);
				else
					PlaySound("igCharacterInfoTab");
					SKMap_ShowSubFrame(tab);
				end
			else
				ShowUIPanel(SKMapFrame);
				SKMap_ShowSubFrame(tab);
			end
		end
	end

end


function SKMap_ShowSubFrame(frameName)
	local FName = "SKMap_ShowSubFrame";

	for index, value in SKM_TAB_SUBFRAMES do
		MyFrame = getglobal(value);
		if (MyFrame) then
			if ( value == frameName ) then
				MyFrame:Show();
			else
				MyFrame:Hide();
			end
		end
	end
end


function SKMapFrame_OnLoad()
  	-- Tab Handling code
  	PanelTemplates_SetNumTabs(this, 4);
  	PanelTemplates_SetTab(this, 1);
  	--PanelTemplates_DisableTab(this, 4);
end


function SKMapFrame_OnShow()
  	PlaySound("igCharacterInfoOpen");
end


function SKMapFrame_OnHide()
  	PlaySound("igCharacterInfoClose");
end


function SKMapTab_OnClick()
	local FName = "SKMapTab_OnClick";

	local TabName = this:GetName();

	SkM_Trace(FName, 1, "Tab Name = "..snil(TabName));

	if (TabName == "SKMapFrameTab1") then
		SKMap_ToggleUI("SKMap_ListFrame");
	elseif (TabName == "SKMapFrameTab2") then
		SKMap_ToggleUI("SKMap_DuelFrame");
	elseif (TabName == "SKMapFrameTab3") then
		SKMap_ToggleUI("SKMap_ReportFrame");
	elseif (TabName == "SKMapFrameTab4") then
		SKMap_ToggleUI("SKMap_OptionsFrame");
	else
		SkM_Trace(FName, 1, "Unknown tab : "..snil(TabName));
	end

	PlaySound("igCharacterInfoTab");
end


function SKMap_SetCheckOption(i, OptionDef, Column)
	local MyCheckButton = getglobal("SKMap_Options_Button"..i..Column.."Check");
	local CheckText = getglobal("SKMap_Options_Button"..i..Column.."Check".."Text");

	local Option = OptionDef.Value;

	local bValue = SkM_GetOption(Option.Option);
	CheckText:SetText(Option.Text);
	MyCheckButton.tooltipText = Option.Tooltip;

	if (bValue) then
		checked = 1;
	else
		checked = 0;
	end
	MyCheckButton:SetChecked(checked);

	--SKMapSmallTargetInfoFrame:SetPoint("TOPLEFT","SKMapTargetInfoFrame","TOPLEFT",0,0);
	MyCheckButton:SetPoint("TOPLEFT", "SKMap_Options_Button"..i..Column, "TOPLEFT", OptionDef.Offset, 1);

	MyCheckButton:Show();
end

function SKMap_SetSliderOption(i, OptionDef, Column)
	local MySlider = getglobal("SKMap_Options_Button"..i..Column.."Slider");
	local SliderText = getglobal("SKMap_Options_Button"..i..Column.."Slider".."Text");

	local Option = OptionDef.Value;
	local iValue = ifnil(SkM_GetOption(Option.Option), 0);

	MySlider:SetMinMaxValues(Option.minValue, Option.maxValue);
	MySlider:SetValueStep(Option.valueStep);
	MySlider:SetValue(iValue);
	MySlider.tooltipText = Option.Tooltip;
	SliderText:SetText(iValue);

	MySlider:SetPoint("TOPLEFT", "SKMap_Options_Button"..i..Column, "TOPLEFT", OptionDef.Offset, 1);

	MySlider:Show();
end



function HideLineOption(i)
	local OptionLabel = getglobal("SKMap_Options_Button"..i.."Label");
	local MySlider = getglobal("SKMap_Options_Button"..i.."Slider");
	local MyCheckButton = getglobal("SKMap_Options_Button"..i.."Check");
	local MyIconTexture = getglobal("SKMap_Options_Button"..i.."IconTexture");

	OptionLabel:Hide();
	MySlider:Hide();
	MyCheckButton:Hide();
	MyIconTexture:Hide();

	local OptionLabelR = getglobal("SKMap_Options_Button"..i.."R".."Label");
	local MySliderR = getglobal("SKMap_Options_Button"..i.."R".."Slider");
	local MyCheckButtonR = getglobal("SKMap_Options_Button"..i.."R".."Check");
	local MyIconTextureR = getglobal("SKMap_Options_Button"..i.."R".."IconTexture");

	OptionLabelR:Hide();
	MySliderR:Hide();
	MyCheckButtonR:Hide();
	MyIconTextureR:Hide();
end

function SKMap_GetOptionLineCount()
	local iCount = 0;
	for i=1,table.getn(SKM_OptionsList),1 do
		if (SKM_OptionsList[i].Expanded) then
			iCount = iCount + table.getn(SKM_OptionsList[i].Lines) + 2;
		else
			iCount = iCount + 1;
		end
	end
	return iCount;
end

function SKMap_OptionsFrame_Load()
	local FName = "SKMap_OptionsFrame_Load";

	SkM_Trace(FName, 4, "Loading frame options values");

	local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_OptionsScrollFrame);

	SkM_Trace(FName, 0, "Scroll offset = "..snil(iScrollOffset));

	local iSkipped = 0;

	SKM_List_Options = { };

	local i;
	for i=1,SKM_OPTIONFRAME_ROWS, 1 do
		HideLineOption(i);
	end

	local iOptionCateg = 1;
	local iOptionElem = 0;
	local i = 0;
	while (true) do
		i = i + 1;
		if (i > SKM_OPTIONFRAME_ROWS) then
			do break end;
		end


		if (iOptionCateg > table.getn(SKM_OptionsList)) then
			do break end;
		end

		if (iOptionCateg <= table.getn(SKM_OptionsList)) then

			-- initially set all categories to expanded mode
			if (SKM_OptionsList[iOptionCateg].Expanded == nil) then
				SKM_OptionsList[iOptionCateg].Expanded = true;
			end

			local bSkip = false;

			if (iSkipped < iScrollOffset) then
				iSkipped = iSkipped + 1;
				i = i - 1;
				bSkip = true;
			end

			if (iOptionElem == -1) then
				-- skip line
				iOptionElem = iOptionElem + 1;
			elseif (iOptionElem == 0) then

				if (not bSkip) then
					-- set category label
					local OptionLabel = getglobal("SKMap_Options_Button"..i.."Label");
					local MyIconTexture = getglobal("SKMap_Options_Button"..i.."IconTexture");

					OptionLabel:SetText(SKM_OptionsList[iOptionCateg].Title.Text);
					OptionLabel:Show();

					local sTexture;
					if (SKM_OptionsList[iOptionCateg].Expanded) then
						--sTexture = SKM_Config.IconPath.."\\"..SKM_Config.Buttons.CollapseButton;
						sTexture = "Interface\\Buttons\\UI-MinusButton-Up"
					else
						--sTexture = SKM_Config.IconPath.."\\"..SKM_Config.Buttons.ExpandButton;
						sTexture = "Interface\\Buttons\\UI-PlusButton-Up"
					end
					MyIconTexture:SetTexture(sTexture);

					--MyIconTexture:SetTexture("Interface\\Buttons\\UI-MinusButton-Up");
					--MyIconTexture:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");

					MyIconTexture:Show();

					SKM_List_Options[i] = { };
					SKM_List_Options[i].Category = iOptionCateg;
				end

				if (SKM_OptionsList[iOptionCateg].Expanded) then
					iOptionElem = iOptionElem + 1;
				else
					iOptionCateg = iOptionCateg + 1;
				end

			else

				local Line = SKM_OptionsList[iOptionCateg].Lines[iOptionElem];
				if (Line and (not bSkip)) then

					SKM_List_Options[i] = { };

					if (Line.Left) then
						SKM_List_Options[i].Left = Line.Left.Value.Option;

						if (Line.Left.Type == _SKM._checkButton) then
							SKMap_SetCheckOption(i, Line.Left, "");
						elseif (Line.Left.Type == _SKM._slider) then
							SKMap_SetSliderOption(i, Line.Left, "");
						end

					end
					if (Line.Right) then
						SKM_List_Options[i].Right = Line.Right.Value.Option;

						if (Line.Right.Type == _SKM._checkButton) then
							SKMap_SetCheckOption(i, Line.Right, "R");
						elseif (Line.Right.Type == _SKM._slider) then
							SKMap_SetSliderOption(i, Line.Right, "R");
						end
					end

				end
				iOptionElem = iOptionElem + 1;

				if (iOptionElem > table.getn(SKM_OptionsList[iOptionCateg].Lines)) then
					iOptionElem = -1;
					iOptionCateg = iOptionCateg + 1;
				end


			end

		end
	end

	local iLineCount = SKMap_GetOptionLineCount() + 1;
	SkM_Trace(FName, 3, "Option Lines = "..snil(iLineCount));

	FauxScrollFrame_Update(SKMap_OptionsScrollFrame, iLineCount, SKM_OPTIONFRAME_ROWS, SKM_OPTIONFRAME_ROWHEIGHT);
end



function SKMap_OptionsFrame_Load_old()
	local FName = "SKMap_OptionsFrame_Load";

	SkM_Trace(FName, 2, "Loading frame options values");

	-- check buttons
	for idx, val in SKM_OptionsFrameCheckButtons do
		local bValue = SkM_GetOption(val.Option);

		SkM_Trace(FName, 3, "Option : "..snil(val.Option)..", Value = "..snil(bValue));

		local MyButton = getglobal("SKMap_OptionsFrameCheckButton"..idx);
		local ButtonText = getglobal("SKMap_OptionsFrameCheckButton"..idx.."Text");
		local checked;

		ButtonText:SetText(val.Text);
		MyButton.tooltipText = val.Tooltip;

		if (bValue) then
			checked = 1;
		else
			checked = 0;
		end

		MyButton:SetChecked(checked);

	end

	-- sliders
	for idx, val in SKM_OptionsFrameSliders do
		local iValue = ifnil(SkM_GetOption(val.Option), 0);

		local MySlider = getglobal("SKMap_OptionsFrameSlider"..idx);
		local SliderText = getglobal("SKMap_OptionsFrameSlider"..idx.."Text");

		MySlider:SetMinMaxValues(val.minValue, val.maxValue);
		MySlider:SetValueStep(val.valueStep);
		MySlider:SetValue(iValue);
		MySlider.tooltipText = val.Tooltip;
		SliderText:SetText(iValue);

	end

	-- labels
	for idx, val in SKM_OptionFrameLabels do

		local MyLabel = getglobal("SKMap_OptionsFrameLabel"..idx.."Text");

		MyLabel:SetText(val.Text);
	end

end



-- obsolete in 1.1.4
function SKMap_OptionsFrame_Save()
	local FName = "SKMap_OptionsFrame_Save";
	local MyButton;

	SkM_Trace(FName, 1, "Saving options");

	-- check buttons
	for idx, val in SKM_OptionsFrameCheckButtons do
		local MyButton = getglobal("SKMap_OptionsFrameCheckButton"..idx);

		if (not MyButton:GetChecked()) then
			SkM_SetOption(val.Option, false);
		else
			SkM_SetOption(val.Option, true);
		end
	end

	-- sliders
	for idx, val in SKM_OptionsFrameSliders do
		local MySlider = getglobal("SKMap_OptionsFrameSlider"..idx);
		local iValue = MySlider:GetValue();

		SkM_SetOption(val.Option, iValue);
	end

end


function SKMap_OptionsFrame_Cancel()
	SKMap_OptionsFrame_Load();
end


-- obsolete since 1.1.4
function SKMap_SetSliderTextToValue()
	local FName = "SKMap_SetSliderTextToValue";

	local SliderName = this:GetName();
	SkM_Trace(FName, 4, "Slider name = "..SliderName);

	local MySlider = getglobal(SliderName);
	local SliderText = getglobal(SliderName.."Text");

	iValue = MySlider:GetValue();
	SliderText:SetText(iValue);


	if (SliderName == "SKMap_OptionsFrameSlider3") then
		SkM_SetOption("MinimapButtonPosition", iValue);
		--SKMap_SetMiniMapIcon(iValue);
		SKMap_SetMiniMapIcon();
	end

	if (SliderName == "SKMap_OptionsFrameSlider4") then
		SkM_SetOption("MinimapButtonOffset", iValue);
		--SKMap_SetMiniMapIcon(iValue);
		SKMap_SetMiniMapIcon();
	end

end


function SKMap_MinimapOption()
	local FName = "SKMap_MinimapOption";

	local OptionName = this:GetName();
	SkM_Trace(FName, 4, "Option name = "..OptionName);

	local MyButton = getglobal(OptionName);

	if (not MyButton:GetChecked()) then
		SkM_SetOption("ShowMinimapButton", false);

	else
		SkM_SetOption("ShowMinimapButton", true);
	end
	SKMap_SetMiniMapIcon();

end


function SKMap_ListFrame_Load()
	local FName = "SKMap_ListFrame_Load";

	SkM_Trace(FName, 1, "Loading ListFrame");

	local idx = 1;
	local MyButton = getglobal("SKMap_ListFrameCheckButton"..idx);
	local ButtonText = getglobal("SKMap_ListFrameCheckButton"..idx.."Text");
	ButtonText:SetText(SKM_UI_STRINGS.List_Button_FilterNoWar);
	MyButton.tooltipText = SKM_UI_STRINGS.List_Tooltip_FilterNoWar;

	if (SKM_List_ActiveList == _SKM._players) then

		if (SKMap_PlayerListUpdateNeeded()) then
			SKMap_SetListContent();
			SKMap_ListFrame_UpdateList();
			SKMap_ListFrame_SortList();
		end

	elseif (SKM_List_ActiveList == _SKM._guilds) then
		SKMap_SetGuildListContent();
		SKMap_ListFrame_UpdateGuildList();
		SKMap_ListFrame_SortGuildList();
	end


end


function SKMap_Column_SetWidth(width, frame)
	if ( not frame ) then
		frame = this;
	end
	frame:SetWidth(width);
	getglobal(frame:GetName().."Middle"):SetWidth(width - 9);
end



function SKMap_ListFrame_UpdateList()
	local FName = "SKMap_ListFrame_UpdateList";

	local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_ListScrollFrame);

	SkM_Trace(FName, 4, "Scrollbar offset = "..snil(iScrollOffset));


	local iEnemyCount = table.getn(SKM_List_Content);
	SkM_Trace(FName, 4, "Enemy Count = "..snil(iEnemyCount));

	local iEnemyIndex = iScrollOffset + 1;

	SkM_Trace(FName, 4, "Enemy Index = "..snil(iEnemyIndex));

	local i;
	for i=1, SKM_LISTFRAME_ROWS, 1 do
		local RowButton = getglobal("SKMap_ListFrameButton"..i);

		if (iEnemyIndex <= iEnemyCount) then

			RowButtonName = getglobal("SKMap_ListFrameButton"..i.."Name");
			RowButtonGuild = getglobal("SKMap_ListFrameButton"..i.."Guild");
			RowButtonLevel = getglobal("SKMap_ListFrameButton"..i.."Level");
			RowButtonRace = getglobal("SKMap_ListFrameButton"..i.."Race");
			RowButtonClass = getglobal("SKMap_ListFrameButton"..i.."Class");
			RowButtonKill = getglobal("SKMap_ListFrameButton"..i.."Kill");
			RowButtonDeath = getglobal("SKMap_ListFrameButton"..i.."Death");
			RowButtonMet = getglobal("SKMap_ListFrameButton"..i.."Met");
			RowButtonLastSeen = getglobal("SKMap_ListFrameButton"..i.."LastSeen");
			RowButtonAtWar = getglobal("SKMap_ListFrameButton"..i.."AtWar");

			local sName = ifnil(SKM_List_Content[iEnemyIndex][_SKM._name], "??");
			local sGuild = ifnil(SKM_List_Content[iEnemyIndex][_SKM._guild], "??");
			local sLevel = ifnil(SKM_List_Content[iEnemyIndex][_SKM._level], "??");

			local sRace = ifnil(SKM_List_Content[iEnemyIndex][_SKM._race], "??");
			local sClass = ifnil(SKM_List_Content[iEnemyIndex][_SKM._class], "??");
			local sLastSeen = ifnil(SKM_List_Content[iEnemyIndex][_SKM._lastView], "??");

			local bAtWar = SKM_List_Content[iEnemyIndex][_SKM._atWar];

			local sGuild = SKM_List_Content[iEnemyIndex][_SKM._guild];

			local Guild;
			if (sGuild ~= nil) and (sGuild ~= "") then
				Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[sGuild];
			end

			local bGuildWar;
			if (Guild) then
				bGuildWar = Guild[_SKM._atWar];
			end

			if (bAtWar) then
				sName = SKM_Config.Col_PlayerWar..sName;
			end
			if (bGuildWar) then
				sGuild = SKM_Config.Col_PlayerWar..sGuild;
			end

			local sWar = "";
			-- 0.08.1 Begin of modification: localization
			if (bAtWar and bGuildWar) then
				sWar = SKM_Config.Col_PlayerWar..SKMAP_COLUMN_ATWAR_ALL;
			elseif (bAtWar) then
				sWar = SKM_Config.Col_PlayerWar..SKMAP_COLUMN_ATWAR_PLAYER;
			elseif (bGuildWar) then
				sWar = SKM_Config.Col_PlayerWar..SKMAP_COLUMN_ATWAR_GUILD;
			end
			-- 0.08.1 End of modification: localization


			local iKill = ifnil(SKM_List_Content[iEnemyIndex][_SKM._playerKill], 0) + ifnil(SKM_List_Content[iEnemyIndex][_SKM._playerAssistKill], 0) + ifnil(SKM_List_Content[iEnemyIndex][_SKM._playerFullKill], 0);
			local iDeath = ifnil(SKM_List_Content[iEnemyIndex][_SKM._enemyKillPlayer], 0);
			local iMet = ifnil(SKM_List_Content[iEnemyIndex][_SKM._meetCount], 0);

			if (sLevel == -1) then
				sLevel = "++";
			end

			RowButtonName:SetText(sName);
			RowButtonGuild:SetText(sGuild);
			RowButtonLevel:SetText(sLevel);
			RowButtonRace:SetText(sRace);
			RowButtonClass:SetText(sClass);

			RowButtonKill:SetText(iKill);
			RowButtonDeath:SetText(iDeath);
			RowButtonMet:SetText(iMet);
			RowButtonLastSeen:SetText(sLastSeen);
			RowButtonAtWar:SetText(sWar);

			RowButton:Show();

			iEnemyIndex = iEnemyIndex + 1;
		else
			RowButton:Hide();
		end
	end

	FauxScrollFrame_Update(SKMap_ListScrollFrame, iEnemyCount, SKM_LISTFRAME_ROWS, SKM_LISTFRAME_ROWHEIGHT);
end


function SKMap_List_CompareElem(v1, v2, ReverseSort)
	local FName = "SKMap_List_CompareElem";

	SkM_Trace(FName, 4, "v1 = "..snil(v1));
	SkM_Trace(FName, 4, "v2 = "..snil(v2));

	if (v1 == nil) and (v2 ~= nil) then
		return true;
	elseif (v2 == nil) and (v1 ~= nil) then
		return false;
	elseif (v1 ~= nil) and (v2 ~= nil) then

		if (ReverseSort) then
			if (v1 < v2) then
				return false;
			elseif (v2 < v1) then
				return true;
			end
		else
			if (v1 < v2) then
				return true;
			elseif (v2 < v1) then
				return false;
			end
		end
	end

	return;
end


function SKMap_ListFrame_SubSort(e1, e2, SortType, ReverseSort)
	local FName = "SKMap_ListFrame_SubSort";

	SkM_Trace(FName, 4, "SortType = "..snil(SortType));

	if (SortType == "Name") then
		--local sName1 = string.upper(e1[_SKM._name]);
		local sName1 = SkM_NormalizeString(e1[_SKM._name]);
		--local sName2 = string.upper(e2[_SKM._name]);
		local sName2 = SkM_NormalizeString(e2[_SKM._name]);
		local bCmp = SKMap_List_CompareElem(sName1, sName2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Guild") then
		-- some dumb people started their guild name with a lowercase character. convert it to upper
		-- before sorting
		--local sGuild1 = string.upper(ifnil(e1[_SKM._guild], "??"));
		local sGuild1 = SkM_NormalizeString(ifnil(e1[_SKM._guild], "??"));
		--local sGuild2 = string.upper(ifnil(e2[_SKM._guild], "??"));
		local sGuild2 = SkM_NormalizeString(ifnil(e2[_SKM._guild], "??"));
		local bCmp = SKMap_List_CompareElem(sGuild1, sGuild2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Level") then
		local iLevel1 = ifnil(e1[_SKM._level], 0);
		local iLevel2 = ifnil(e2[_SKM._level], 0);
		if (iLevel1 == -1) then
			iLevel1 = 500;
		end
		if (iLevel2 == -1) then
			iLevel2 = 500;
		end
		local bCmp = SKMap_List_CompareElem(iLevel1, iLevel2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Race") then
		local bCmp = SKMap_List_CompareElem(ifnil(e1[_SKM._race], ""), ifnil(e2[_SKM._race], ""), ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Class") then
		local bCmp = SKMap_List_CompareElem(ifnil(e1[_SKM._class], ""), ifnil(e2[_SKM._class], ""), ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Kill") then
		local iKill1 = ifnil(e1[_SKM._playerKill], 0) + ifnil(e1[_SKM._playerAssistKill], 0) + ifnil(e1[_SKM._playerFullKill], 0);
		local iKill2 = ifnil(e2[_SKM._playerKill], 0) + ifnil(e2[_SKM._playerAssistKill], 0) + ifnil(e2[_SKM._playerFullKill], 0);

		local bCmp = SKMap_List_CompareElem(iKill1, iKill2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Death") then
		local iDeath1 = ifnil(e1[_SKM._enemyKillPlayer], 0);
		local iDeath2 = ifnil(e2[_SKM._enemyKillPlayer], 0);

		local bCmp = SKMap_List_CompareElem(iDeath1, iDeath2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Met") then
		local iMet1 = ifnil(e1[_SKM._meetCount], 0);
		local iMet2 = ifnil(e2[_SKM._meetCount], 0);

		local bCmp = SKMap_List_CompareElem(iMet1, iMet2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "LastSeen") then
		local sDate1 = SkM_GetSortableDate(e1[_SKM._lastView]);
		local sDate2 = SkM_GetSortableDate(e2[_SKM._lastView]);

		local bCmp = SKMap_List_CompareElem(ifnil(sDate1, ""), ifnil(sDate2, ""), ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "AtWar") then
		local sWar1 = "";
		local sWar2 = "";
		if (e1[_SKM._atWar]) or (e1[_SKM._guildAtWar]) then
			sWar1 = "WAR";
		end
		if (e2[_SKM._atWar]) or (e2[_SKM._guildAtWar]) then
			sWar2 = "WAR";
		end

		local bCmp = SKMap_List_CompareElem(sWar1, sWar2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Members") then
		local iMembers1 = ifnil(e1[_SKM._members], 0);
		local iMembers2 = ifnil(e2[_SKM._members], 0);

		local bCmp = SKMap_List_CompareElem(iMembers1, iMembers2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Win") then
		local iWin1 = ifnil(e1[_SKM._win], 0);
		local iWin2 = ifnil(e2[_SKM._win], 0);

		local bCmp = SKMap_List_CompareElem(iWin1, iWin2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Loss") then
		local iLoss1 = ifnil(e1[_SKM._loss], 0);
		local iLoss2 = ifnil(e2[_SKM._loss], 0);

		local bCmp = SKMap_List_CompareElem(iLoss1, iLoss2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Duel") then
		local iDuel1 = ifnil(e1[_SKM._duel], 0);
		local iDuel2 = ifnil(e2[_SKM._duel], 0);

		local bCmp = SKMap_List_CompareElem(iDuel1, iDuel2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "LastDuel") then
		local sDate1 = SkM_GetSortableDate(e1[_SKM._lastDuel]);
		local sDate2 = SkM_GetSortableDate(e2[_SKM._lastDuel]);

		local bCmp = SKMap_List_CompareElem(ifnil(sDate1, ""), ifnil(sDate2, ""), ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	elseif (SortType == "Score") then
		local iScore1 = ifnil(e1[_SKM._score], 0);
		local iScore2 = ifnil(e2[_SKM._score], 0);

		local bCmp = SKMap_List_CompareElem(iScore1, iScore2, ReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end

	end
	return nil;
end


function SKMap_ListFrame_Sort(e1, e2)
	local FName = "SKMap_ListFrame_Sort";

	SkM_Trace(FName, 4, "Begin");

	if (e1 == nil) then
		if (e2 == nil) then
			return false;
		else
			return true;
		end
	elseif (e2 == nil) then
		return false;
	end

	--local iSortTypes = table.getn(SKM_List_SortTypes);
	local iSortTypes = table.getn( SkM_GetOption("EnemyList_SortTypes") );

	local i;
	for i=1, iSortTypes, 1 do
		local bReverseSort = false;
		--if (i == 1) and (SKM_List_ReverseSort == true) then
		if (i == 1) and ( SkM_GetOption("EnemyList_ReverseSort") ) then
			bReverseSort = true;
		end
		--local bCmp = SKMap_ListFrame_SubSort(e1, e2, SKM_List_SortTypes[i], bReverseSort);
		local bCmp = SKMap_ListFrame_SubSort(e1, e2, SkM_GetOption("EnemyList_SortTypes")[i], bReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end
	end
	return false;
end


function SKMap_ListFrame_SortList(sSortType)
	local FName = "SKMap_ListFrame_SortList";

	if (sSortType) then
		--if (sSortType == SKM_List_SortType) then
		if (sSortType == SkM_GetOption("EnemyList_SortType")) then
			--if (SKM_List_ReverseSort) then
			if ( SkM_GetOption("EnemyList_ReverseSort") ) then
				--SKM_List_ReverseSort = false;
				SkM_SetOption("EnemyList_ReverseSort", false);
			else
				--SKM_List_ReverseSort = true;
				SkM_SetOption("EnemyList_ReverseSort", true);
			end
		else
			--SKM_List_SortType = sSortType;
			SkM_SetOption("EnemyList_SortType", sSortType);

			--SKM_List_SortTypes = removefromlist(sSortType, SKM_List_SortTypes);
			SKM_Settings.EnemyList_SortTypes = removefromlist(sSortType, SkM_GetOption("EnemyList_SortTypes") );
			--table.insert(SKM_List_SortTypes, 1, sSortType);
			table.insert(SKM_Settings.EnemyList_SortTypes, 1, sSortType);
		end
	end

	if (SKM_List_Content) then
		table.sort(SKM_List_Content, SKMap_ListFrame_Sort);
	end

	SKMap_ListFrame_UpdateList();
end


function SKMap_SetListContent()
	local FName = "SKMap_SetListContent";

	SKM_List_Content = { };

	local idx, val;
	for idx, val in SKM_Data[_RealmName][_PlayerName].EnemyHistory do
		local Elem = copytable(val);

		if (Elem[_SKM._guild] == "not in a guild") then
			SKM_Data[_RealmName][_PlayerName].EnemyHistory[idx][_SKM._guild] = "";
		end

		Elem[_SKM._class] = SkM_GetClassText(Elem[_SKM._class]);
		Elem[_SKM._race] = SkM_GetRaceText(Elem[_SKM._race]);

		-- also retrieve guild "at war" status
		local Guild;
		if (Elem[_SKM._guild] ~= nil) and (Elem[_SKM._guild] ~= "") then
			Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[val[_SKM._guild]];
		end
		if (Guild) and (Guild[_SKM._atWar]) then
			Elem[_SKM._guildAtWar] = true;
		end

		-- check if element has to be filtered out or not
		local bFilter = false;
		if (SKM_Config.FilterNotAtWar == true) then
			if ( not ((Elem[_SKM._atWar]) or (Elem[_SKM._guildAtWar])) ) then
				bFilter = true;
			end
		end

		if (bFilter == false) then
			table.insert(SKM_List_Content, Elem);
		end
	end

end


function SKMap_ListFrame_SelectElement(sPlayerName)
	local FName = "SKMap_ListFrame_SelectElement";

	local sName;

	if (sPlayerName ~= nil) then
		sName = sPlayerName;
	else
		local id = this:GetID();
		local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_ListScrollFrame);
		local iEnemyCount = table.getn(SKM_List_Content);

		SkM_Trace(FName, 3, "Scroll offset = "..iScrollOffset);
		SkM_Trace(FName, 3, "Line id = "..id);

		local iEnemyIndex = iScrollOffset + id;
		SkM_Trace(FName, 3, "Enemy Index = "..iEnemyIndex);

		if (iEnemyIndex <= iEnemyCount) then
			sName = SKM_List_Content[iEnemyIndex][_SKM._name];
		end

	end

	local Enemy;
	if (sName ~= nil) then
		Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[sName];
	end

	local Lines = { };

	if (Enemy ~= nil) then
		SKM_List_SelectedPlayer = sName;

		local Guild;

		local sGuild = ifnil(Enemy[_SKM._guild], "??");
		local sLevel = ifnil(Enemy[_SKM._level], "??");
		local sRace = ifnil(SkM_GetRaceText(Enemy[_SKM._race]), "??");
		local sClass = ifnil(SkM_GetClassText(Enemy[_SKM._class]), "??");
		local sLastSeen = ifnil(Enemy[_SKM._lastView], "??");

		local iKill = ifnil(Enemy[_SKM._playerKill], 0);
		local iAssistKill = ifnil(Enemy[_SKM._playerAssistKill], 0);
		local iFullKill = ifnil(Enemy[_SKM._playerFullKill], 0);
		local iTotalKill = iKill + iAssistKill + iFullKill;
		local iDeath = ifnil(Enemy[_SKM._enemyKillPlayer], 0);
		local iMet = ifnil(Enemy[_SKM._meetCount], 0);
		local iLoneWolf = ifnil(Enemy[_SKM._loneWolfKill], 0);
		local iBGKill = ifnil(Enemy[_SKM._playerBGKill], 0);
		local iBGDeath = ifnil(Enemy[_SKM._enemyKillBG], 0);

		if (sLevel == -1) then
			sLevel = "++";
		end

		local bAtWar;
		if (Enemy[_SKM._atWar]) then
			bAtWar = true;
		else
			bAtWar = false;
		end

		SKMap_ListFrame_ShowWarButton(bAtWar);

		local bGuildWar;
		if (Enemy[_SKM._guild] ~= nil) and (Enemy[_SKM._guild] ~= "") then
			Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[sGuild];
		end
		if (Guild ~= nil) then
			bGuildWar = Guild[_SKM._atWar];
			SKMap_ListFrame_ShowPlayerGuildButton:Show();
		else
			SKMap_ListFrame_ShowPlayerGuildButton:Hide();
		end

		SKMap_ListFrame_EditNote:Show();
		SKMap_ListFrame_ReportButton:Show();
		SKMap_ListFrame_DeleteButton:Show();
		SKMap_ListFrame_BackToPlayersButton:Hide();

		-- line 1 : player name and (optional) war status
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Player; -- 0.08.2 Add localization
		if (Enemy[_SKM._rank]) then
			sLine = sLine..SKM_Config.Col_Rank..Enemy[_SKM._rank].." ";
		end
		if (bAtWar) then
			sLine = sLine..SKM_Config.Col_PlayerWar;
		else
			sLine = sLine..SKM_Config.Col_Label;
		end
		sLine = sLine..sName..SKM_Config.Col_Label;
		if (bAtWar) then
			sLine = sLine.."  -  "..SKM_Config.Col_PlayerWar..SKM_UI_STRINGS.Small_Target_War;
			if (Enemy[_SKM._warDate]) then
				--local sDisplayDate = string.sub(Enemy[_SKM._warDate], 1, 10);
				local sDisplayDate = Enemy[_SKM._warDate];
				sLine = sLine.." "..SKM_UI_STRINGS.Since..sDisplayDate;
			end
		end

		table.insert(Lines, sLine);


		-- line 2 (optional) : player guild and (optional) war status
		if (Guild ~= nil) then

			local sLine = "";
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Guild; -- 0.08.2 Add localization

			if (bGuildWar) then
				sLine = sLine..SKM_Config.Col_PlayerWar;
			else
				sLine = sLine..SKM_Config.Col_Label;
			end

			sLine = sLine..sGuild..SKM_Config.Col_Label;
			if (bGuildWar) then
				sLine = sLine.."  -  "..SKM_Config.Col_PlayerWar..SKM_UI_STRINGS.Small_Target_War;
				if (Guild[_SKM._warDate]) then
					--local sDisplayDate = string.sub(Guild[_SKM._warDate], 1, 10);
					local sDisplayDate = Guild[_SKM._warDate];
					sLine = sLine.." "..SKM_UI_STRINGS.Since..sDisplayDate;
				end
				--sLine = sLine..SKM_Config.Col_Label.."]";
			end

			table.insert(Lines, sLine);
		end


		-- line 3 (optional, not shown if info not available) : level race class
		if (Enemy[_SKM._level] ~= nil) and (Enemy[_SKM._race] ~= nil) and (Enemy[_SKM._class] ~= nil) then

			local sLine = "";
			sLine = sLine..SKM_Config.Col_Label..SKM_UI_STRINGS.List_Frame_Level..sLevel.." "..sRace.." "..sClass; -- 0.08.2 Add localization

			table.insert(Lines, sLine);
		end


		-- line 4 : last seen time and location
		if (Enemy[_SKM._lastView] ~= nil) then

			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Last_Seen; -- 0.08.2 Add localization
			sLine = sLine..SKM_Config.Col_Label..Enemy[_SKM._lastView];

			if (Enemy[_SKM._continent] ~= nil) and (Enemy[_SKM._zone] ~= nil) then
				--local sZoneText = SKM_Context.Zones[Enemy[_SKM._continent]][Enemy[_SKM._zone]];
				local sZoneText = SkM_GetZoneTextFromIndex(Enemy[_SKM._continent], Enemy[_SKM._zone]);
				sLine = sLine.." - "..sZoneText;
			elseif (Enemy[_SKM._zoneName] ~= nil) then
				sLine = sLine.." - "..Enemy[_SKM._zoneName];
			end

			table.insert(Lines, sLine);
		end


		-- line 5 : last update time (optional, only if different from last seen time)
--		if (Enemy[_lastUpdate] ~= nil) and (not Enemy[_lastUpdate] == Enemy[_SKM._lastView]) then
--			local sLine = "";
--			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Last_Updated; -- 0.08.2 Add localization
--			sLine = sLine..SKM_Config.Col_Label..Enemy[_lastUpdate];
--			table.insert(Lines, sLine);
--		end


		-- line 6 : meet and death counts
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Met..SKM_Config.Col_PlayerMet..iMet; -- 0.08.2 Add localization
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Death..SKM_Config.Col_PlayerDeath .. iDeath; -- 0.08.2 Add localization
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_LoneWolf..SKM_Config.Col_LoneWolfKill .. iLoneWolf;

		table.insert(Lines, sLine);


		-- line 7 : kill counts
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Kill..SKM_Config.Col_PlayerTotalKill..iTotalKill; -- 0.08.2 Add localization
		sLine = sLine.."   "..SKM_Config.Col_Label.."( ";
		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Full..SKM_Config.Col_PlayerFullKill..iFullKill; -- 0.08.2 Add localization
		sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Standard..SKM_Config.Col_PlayerKill..iKill; -- 0.08.2 Add localization
		sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Assist..SKM_Config.Col_PlayerAssistKill..iAssistKill..SKM_Config.Col_Label.." )"; -- 0.08.2 Add localization

		table.insert(Lines, sLine);


		-- Line : honor kills and remaining potential kills today
		local sLine = "";

		if (ifnil(Enemy[_SKM._honorKill], 0) > 0) then
			local iRemaining = SkM_GetHonorRemainingKills(sName);
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_HonorKill..SKM_Config.Col_HonorKill..Enemy[_SKM._honorKill];
			if (iRemaining == 0) then
				sLine = sLine..SKM_Config.Col_Label.."   ( "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_RemainHonor..SKM_Config.Col_Honorless..iRemaining..SKM_Config.Col_Label.." )";
			else
				sLine = sLine..SKM_Config.Col_Label.."   ( "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_RemainHonor..SKM_Config.Col_HonorKill..iRemaining..SKM_Config.Col_Label.." )";
			end
			sLine = sLine.."     ";
		end

		if (iBGKill > 0 or iBGDeath > 0) then
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_BGKill..SKM_Config.Col_BGKill .. iBGKill;
			sLine = sLine.."     ";
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_BGDeath..SKM_Config.Col_BGDeath .. iBGDeath;
		end

		if (sLine ~= "") then
			table.insert(Lines, sLine);
		end

		-- line 8 : player notes
		if (Enemy[_SKM._playerNote] ~= nil) and (Enemy[_SKM._playerNote] ~= "") then
			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Note; -- 0.08.2 Add localization
			sLine = sLine..SKM_Config.Col_Label..Enemy[_SKM._playerNote];

			table.insert(Lines, sLine);
		end


		local i;
		for i=1, SKM_LISTFRAME_DETAIL_ROWS, 1 do
			local ButtonText = getglobal("SKMap_ListFrameDetailButton"..i.."Text");

			if (i <= getn(Lines)) then
				SkM_Trace(FName, 2, i.." : "..Lines[i]);

				if (ButtonText) then
					ButtonText:SetText(Lines[i]);
				end
			else
				ButtonText:SetText("");
			end
		end
	end

end


function SKMap_ListFrame_ClearDetail()
	local i;
	for i=1, SKM_LISTFRAME_DETAIL_ROWS, 1 do
		local ButtonText = getglobal("SKMap_ListFrameDetailButton"..i.."Text");
		if (ButtonText) then
			ButtonText:SetText("");
		end
	end

	SKMap_ListFrameTruceButton:Hide();
	SKMap_ListFrameWarButton:Hide();

	SKMap_ListFrame_ShowPlayerGuildButton:Hide();
	SKMap_ListFrame_BackToPlayersButton:Hide();
	SKMap_ListFrame_EditNote:Hide();
	SKMap_ListFrame_ReportButton:Hide();
	SKMap_ListFrame_DeleteButton:Hide();
end


function SKMap_ListFrame_GuildSort(e1, e2)
	local FName = "SKMap_ListFrame_GuildSort";

	SkM_Trace(FName, 4, "Begin");

	if (e1 == nil) then
		if (e2 == nil) then
			return false;
		else
			return true;
		end
	elseif (e2 == nil) then
		return false;
	end

	--local iSortTypes = table.getn(SKM_GuildList_SortTypes);
	local iSortTypes = table.getn( SkM_GetOption("GuildList_SortTypes") );

	local i;
	for i=1, iSortTypes, 1 do
		local bReverseSort = false;
		--if (i == 1) and (SKM_GuildList_ReverseSort) then
		if (i == 1) and ( SkM_GetOption("GuildList_ReverseSort") ) then
			bReverseSort = true;
		end
		--local bCmp = SKMap_ListFrame_SubSort(e1, e2, SKM_GuildList_SortTypes[i], bReverseSort);
		local bCmp = SKMap_ListFrame_SubSort(e1, e2, SkM_GetOption("GuildList_SortTypes")[i], bReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end
	end
	return false;
end


function SKMap_ListFrame_SortGuildList(sSortType)
	local FName = "SKMap_ListFrame_SortGuildList";

	SkM_Trace(FName, 3, "Sort by : "..snil(sSortType));

	if (sSortType) then
		--if (sSortType == SKM_GuildList_SortType) then
		if (sSortType == SkM_GetOption("GuildList_SortType") ) then

			--if (SKM_GuildList_ReverseSort) then
			if ( SkM_GetOption("GuildList_ReverseSort") ) then
				--SKM_GuildList_ReverseSort = false;
				SkM_SetOption("GuildList_ReverseSort", false);
			else
				--SKM_GuildList_ReverseSort = true;
				SkM_SetOption("GuildList_ReverseSort", true);
			end
		else
			--SKM_GuildList_SortType = sSortType;
			SkM_SetOption("GuildList_SortType", sSortType);

			--SKM_GuildList_SortTypes = removefromlist(sSortType, SKM_GuildList_SortTypes);
			SKM_Settings.GuildList_SortTypes = removefromlist(sSortType, SkM_GetOption("GuildList_SortTypes") );
			--table.insert(SKM_GuildList_SortTypes, 1, sSortType);
			table.insert(SKM_Settings.GuildList_SortTypes, 1, sSortType);
		end
	end

	if (SKM_GuildList_Content) then
		SkM_Trace(FName, 3, "Now sorting guild list");
		table.sort(SKM_GuildList_Content, SKMap_ListFrame_GuildSort);
	end

	SKMap_ListFrame_UpdateGuildList();
end


function SKMap_ListFrame_UpdateGuildList()
	local FName = "SKMap_ListFrame_UpdateGuildList";

	local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_ListGuildScrollFrame);

	SkM_Trace(FName, 4, "Scrollbar offset = "..snil(iScrollOffset));

	local iGuildCount = table.getn(SKM_GuildList_Content);
	SkM_Trace(FName, 4, "Guild Count = "..snil(iGuildCount));

	local iIndex = iScrollOffset + 1;

	SkM_Trace(FName, 4, "Guild Index = "..snil(iIndex));

	local i;
	for i=1, SKM_LISTFRAME_ROWS, 1 do
		local RowButton = getglobal("SKMap_ListFrameGuildButton"..i);

		if (iIndex <= iGuildCount) then

			RowButtonName = getglobal("SKMap_ListFrameGuildButton"..i.."Name");
			RowButtonMembers = getglobal("SKMap_ListFrameGuildButton"..i.."Members");
			RowButtonKill = getglobal("SKMap_ListFrameGuildButton"..i.."Kill");
			RowButtonDeath = getglobal("SKMap_ListFrameGuildButton"..i.."Death");
			RowButtonMet = getglobal("SKMap_ListFrameGuildButton"..i.."Met");
			RowButtonLastSeen = getglobal("SKMap_ListFrameGuildButton"..i.."LastSeen");
			RowButtonAtWar = getglobal("SKMap_ListFrameGuildButton"..i.."AtWar");

			local sName = ifnil(SKM_GuildList_Content[iIndex][_SKM._name], "??");
			local sLastSeen = ifnil(SKM_GuildList_Content[iIndex][_SKM._lastView], "??");

			local bAtWar = SKM_GuildList_Content[iIndex][_SKM._atWar];

			local sWar = "";
			if (bAtWar) then
				sName = SKM_Config.Col_PlayerWar..sName;
				sWar = SKM_Config.Col_PlayerWar..SKMAP_COLUMN_ATWAR_GUILD; -- 0.08.1 Add localization
			end

			local iKill = ifnil(SKM_GuildList_Content[iIndex][_SKM._playerKill], 0) + ifnil(SKM_GuildList_Content[iIndex][_SKM._playerAssistKill], 0) + ifnil(SKM_GuildList_Content[iIndex][_SKM._playerFullKill], 0);
			local iDeath = ifnil(SKM_GuildList_Content[iIndex][_SKM._enemyKillPlayer], 0);
			local iMet = ifnil(SKM_GuildList_Content[iIndex][_SKM._meetCount], 0);
			local iMembers = ifnil(SKM_GuildList_Content[iIndex][_SKM._members], 0);

			RowButtonName:SetText(sName);
			RowButtonMembers:SetText(iMembers);
			RowButtonKill:SetText(iKill);
			RowButtonDeath:SetText(iDeath);
			RowButtonMet:SetText(iMet);
			RowButtonLastSeen:SetText(sLastSeen);
			RowButtonAtWar:SetText(sWar);

			RowButton:Show();

			iIndex = iIndex + 1;
		else
			RowButton:Hide();
		end

	end

	FauxScrollFrame_Update(SKMap_ListGuildScrollFrame, iGuildCount, SKM_LISTFRAME_ROWS, SKM_LISTFRAME_ROWHEIGHT);
end


function SKMap_SetGuildListContent()
	local FName = "SKMap_SetGuildListContent";

	SKM_GuildList_Content = { };

	local idx, val;
	for idx, val in  SKM_Data[_RealmName][_PlayerName].GuildHistory do
		local Elem = copytable(val);

		Elem[_SKM._members] = SkM_CountGuildMembers(idx);

		-- check if element has to be filtered out or not
		local bFilter = false;
		if (SKM_Config.FilterNotAtWar == true) then
			if ( not (Elem[_SKM._atWar]) ) then
				bFilter = true;
			end
		end

		if (bFilter == false) then
			table.insert(SKM_GuildList_Content, Elem);
		end

	end

end


function SKMap_ListFrame_SelectGuild(sGuildName)
	local FName = "SKMap_ListFrame_SelectGuild";

	local sName;

	if (sGuildName ~= nil) then
		sName = sGuildName;
	else
		local id = this:GetID();
		local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_ListGuildScrollFrame);
		local iGuildCount = table.getn(SKM_GuildList_Content);

		SkM_Trace(FName, 3, "Scroll offset = "..iScrollOffset);
		SkM_Trace(FName, 3, "Line id = "..id);

		local iGuildIndex = iScrollOffset + id;
		SkM_Trace(FName, 3, "Guild Index = "..iGuildIndex);

		if (iGuildIndex <= iGuildCount) then
			sName = SKM_GuildList_Content[iGuildIndex][_SKM._name];
		end
	end

	local Guild;
	if (sName ~= nil) and (sName ~= "") then
		Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[sName];
	end



	local Lines = { };

	if (Guild ~= nil) then
		SKM_List_SelectedGuild = sName;

		local sLastSeen = ifnil(Guild[_SKM._lastView], "??");

		local iKill = ifnil(Guild[_SKM._playerKill], 0);
		local iAssistKill = ifnil(Guild[_SKM._playerAssistKill], 0);
		local iFullKill = ifnil(Guild[_SKM._playerFullKill], 0);
		local iTotalKill = iKill + iAssistKill + iFullKill;
		local iDeath = ifnil(Guild[_SKM._enemyKillPlayer], 0);
		local iMet = ifnil(Guild[_SKM._meetCount], 0);
		local iLoneWolf = ifnil(Guild[_SKM._loneWolfKill], 0);

		local iBGKill = ifnil(Guild[_SKM._playerBGKill], 0);
		local iBGDeath = ifnil(Guild[_SKM._enemyKillBG], 0);

		local iMembers = SkM_CountGuildMembers(sName);

		local bAtWar;
		if (Guild[_SKM._atWar]) then
			bAtWar = true;
		else
			bAtWar = false;
		end

		SKMap_ListFrame_ShowWarButton(bAtWar);

		SKMap_ListFrame_ShowPlayerGuildButton:Hide();
		SKMap_ListFrame_BackToPlayersButton:Hide();
		SKMap_ListFrame_EditNote:Show();
		SKMap_ListFrame_ReportButton:Show();
		SKMap_ListFrame_DeleteButton:Hide();


		-- line 1 : guild name and (optional) war status
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle.."Guild :  ";
		if (bAtWar) then
			sLine = sLine..SKM_Config.Col_PlayerWar;
		else
			sLine = sLine..SKM_Config.Col_Label;
		end
		sLine = sLine..sName..SKM_Config.Col_Label;
		if (bAtWar) then
			sLine = sLine.."  -  "..SKM_Config.Col_PlayerWar..SKM_UI_STRINGS.Small_Target_War;
			if (Guild[_SKM._warDate]) then
				--local sDisplayDate = string.sub(Enemy[_SKM._warDate], 1, 10);
				local sDisplayDate = Guild[_SKM._warDate];
				sLine = sLine.." "..SKM_UI_STRINGS.Since..sDisplayDate;
			end
		end

		table.insert(Lines, sLine);


		-- Line 2 : members
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Guild_Member; -- 0.08.2 Add localization
		sLine = sLine..SKM_Config.Col_Label..iMembers;

		table.insert(Lines, sLine);


		-- line 3 : last seen time and last player viewed
		if (Guild[_SKM._lastView] ~= nil) then

			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Last_Seen; -- 0.08.2 Add localization

			if (Guild[_SKM._lastPlayerViewed] ~= nil) then
				sLine = sLine..SKM_Config.Col_Label..Guild[_SKM._lastPlayerViewed].." - ";
			end

			sLine = sLine..SKM_Config.Col_Label..Guild[_SKM._lastView];

			table.insert(Lines, sLine);
		end


		-- line 4 : meet and death counts
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Met..SKM_Config.Col_PlayerMet..iMet; -- 0.08.2 Add localization
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Death..SKM_Config.Col_PlayerDeath .. iDeath; -- 0.08.2 Add localization
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_LoneWolf..SKM_Config.Col_LoneWolfKill .. iLoneWolf;

		table.insert(Lines, sLine);


		-- line 5 : kill counts
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Kill..SKM_Config.Col_PlayerTotalKill..iTotalKill; -- 0.08.2 Add localization
		sLine = sLine.."   "..SKM_Config.Col_Label.."( ";
		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Full..SKM_Config.Col_PlayerFullKill..iFullKill; -- 0.08.2 Add localization
		sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Standard..SKM_Config.Col_PlayerKill..iKill; -- 0.08.2 Add localization
		sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Assist..SKM_Config.Col_PlayerAssistKill..iAssistKill..SKM_Config.Col_Label.." )"; -- 0.08.2 Add localization

		table.insert(Lines, sLine);


		-- Line : honor kills
		local sLine = "";

		if (ifnil(Guild[_SKM._honorKill], 0) > 0) then
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_HonorKill..SKM_Config.Col_HonorKill..Guild[_SKM._honorKill];
			sLine = sLine.."     ";
		end

		if (iBGKill > 0 or iBGDeath > 0) then
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_BGKill..SKM_Config.Col_BGKill .. iBGKill;
			sLine = sLine.."     ";
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_BGDeath..SKM_Config.Col_BGDeath .. iBGDeath;
		end

		if (sLine ~= "") then
			table.insert(Lines, sLine);
		end



		-- line 6 : player notes
		if (Guild[_SKM._playerNote] ~= nil) and (Guild[_SKM._playerNote] ~= "") then
			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Note; -- 0.08.2 Add localization
			sLine = sLine..SKM_Config.Col_Label..Guild[_SKM._playerNote];

			table.insert(Lines, sLine);
		end


		local i;
		for i=1, SKM_LISTFRAME_DETAIL_ROWS, 1 do
			local ButtonText = getglobal("SKMap_ListFrameDetailButton"..i.."Text");

			if (i <= getn(Lines)) then
				SkM_Trace(FName, 2, i.." : "..Lines[i]);

				if (ButtonText) then
					ButtonText:SetText(Lines[i]);
				end
			else
				ButtonText:SetText("");
			end
		end
	end

end


function SKMap_ListFrame_ToggleLists()
	local FName = "SKMap_ListFrame_ToggleLists";

	if (SKM_List_ActiveList == _SKM._players) then

		SKM_List_ActiveList = _SKM._guilds;

		SKMap_ListFrame_Load();

		SKMap_ListFrameMainList:Hide();
		SKMap_ListFrameGuildList:Show();

		SKMap_ListFrame_UpdateListButton:Hide();

		SKMap_ListFrame_ToggleButton:SetText(SKMAP_PLAYERS);

		if (SKM_List_SelectedGuild ~= nil) then
			SKMap_ListFrame_SelectGuild(SKM_List_SelectedGuild);
		else
			SKMap_ListFrame_ClearDetail();
		end

	else

		SKM_List_ActiveList = _SKM._players;

		SKMap_ListFrame_Load();

		SKMap_ListFrameGuildList:Hide();
		SKMap_ListFrameMainList:Show();

		SKMap_ListFrame_UpdateListButton:Show();

		SKMap_ListFrame_ToggleButton:SetText(SKMAP_GUILDS);

		if (SKM_List_SelectedPlayer ~= nil) then
			SKMap_ListFrame_SelectElement(SKM_List_SelectedPlayer);
		else
			SKMap_ListFrame_ClearDetail();
		end

	end

end


function SKMap_ListFrame_Filter()
	local FName = "SKMap_ListFrame_Filter";

	local MyButton = getglobal("SKMap_ListFrameCheckButton1");

	SKM_Config.FilterNotAtWar = false;
	if (MyButton:GetChecked()) then
		SKM_Config.FilterNotAtWar = true;
	end

	SKMap_ListFrame_Load();
end


function SKMap_ListDetail_SetWar()
	local FName = "SKMap_ListDetailWar";

	if (SKM_List_ActiveList == _SKM._players) then
		if (SKM_List_SelectedPlayer ~= nil) then
			local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[SKM_List_SelectedPlayer];
			if (Enemy) then
				local bWar;
				if (Enemy[_SKM._atWar]) then
					bWar = false;
				else
					bWar = true;
				end

				local sDate = SkM_GetDate();

				SkM_UpdateEnemy_SetWar(SKM_List_SelectedPlayer, bWar, sDate);
				SKMap_ListFrame_ShowWarButton(bWar);

				SKMap_ListFrame_UpdateList();
				SKMap_ListFrame_SelectElement(SKM_List_SelectedPlayer);
			end
		end
	else
		if (SKM_List_SelectedGuild ~= nil) and (SKM_List_SelectedGuild ~= "") then
			local Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[SKM_List_SelectedGuild];
			if (Guild) then
				local bWar;
				if (Guild[_SKM._atWar]) then
					bWar = false;
				else
					bWar = true;
				end

				local sDate = SkM_GetDate();

				SkM_UpdateGuild_SetWar(SKM_List_SelectedGuild, bWar, sDate);
				SKMap_ListFrame_ShowWarButton(bWar);

				SKMap_ListFrame_UpdateGuildList();
				SKMap_ListFrame_SelectGuild(SKM_List_SelectedGuild);
			end
		end
	end

end


function SKMap_ListFrame_ShowWarButton(bWar)
	local FName = "SKMap_ListFrame_ShowWarButton";

	SkM_Trace(FName, 2, "War = "..snil(bWar));

	if (bWar == nil) then
		SKMap_ListFrameTruceButton:Hide();
		SKMap_ListFrameWarButton:Hide();
	elseif (bWar == true) then
		SKMap_ListFrameTruceButton:Show();
		SKMap_ListFrameWarButton:Hide();

	elseif (bWar == false) then
		SKMap_ListFrameTruceButton:Hide();
		SKMap_ListFrameWarButton:Show();
	end
end



function SKMap_List_ShowPlayerGuild()
	if (SKM_List_ActiveList == _SKM._players) then
		if (SKM_List_SelectedPlayer ~= nil) then
			local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[SKM_List_SelectedPlayer];
			if (Enemy) then
				local sGuild = Enemy[_SKM._guild];
				if (sGuild ~= nil) and (sGuild ~= "") then
					local Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[sGuild];
					if (Guild) then
						SKM_List_SelectedGuild = sGuild;
						SKMap_ListFrame_ToggleLists();
						SKMap_ListFrame_BackToPlayersButton:Show();

					end
				end
			end
		end
	end
end


function SKMap_List_BackToPlayers()
	SKMap_ListFrame_ToggleLists();
end


function SKMap_Report_WriteBook(Lines)
	local FName = "SKMap_Report_WriteBook";

	local i, j;
	local iNbLines = table.getn(Lines);
	for i=1, SKM_BOOKFRAME_ROWS, 1 do

		local ButtonText = getglobal("SKMap_ReportFrameBookButton"..i.."Text");
		local ButtonCols = { };

		for j=1, SKM_BOOKFRAME_COLUMNS, 1 do
			local ButtonCol = getglobal("SKMap_ReportFrameBookButton"..i.."Col"..j);
			table.insert(ButtonCols, ButtonCol);
		end

		if (i <= iNbLines) then
			local CurrentLine = Lines[i];

			if (type(CurrentLine) == "string" ) then
				ButtonText:SetText(Lines[i]);
				ButtonText:Show();
				for j=1, SKM_BOOKFRAME_COLUMNS, 1 do
					ButtonCols[j]:SetText("");
					ButtonCols[j]:Hide();
				end

			elseif (type(CurrentLine) == "table" ) then

				local iNbCols = table.getn(Lines[i]);

				for j=1, SKM_BOOKFRAME_COLUMNS, 1 do
					if (j <= iNbCols) then
						ButtonCols[j]:SetText(Lines[i][j]);
					else
						ButtonCols[j]:SetText("");
					end
					ButtonCols[j]:Show();
				end

				ButtonText:SetText("");
				ButtonText:Hide();

			else
				-- unknown variable type !!!
				SkM_Trace(FName, 1, "Unknown variable type for line "..i);
			end


		else
			-- no more to write, hide our text strings
			ButtonText:SetText("");
			ButtonText:Hide();
			for j=1, SKM_BOOKFRAME_COLUMNS, 1 do
				ButtonCols[j]:SetText("");
				ButtonCols[j]:Hide();
			end

		end
	end
end


function SKMap_ReportFrame_Load()
	local FName = "SKMap_ReportFrame_Load";

	local idx = 1;
	local MyButton = getglobal("SKMap_ReportFrameCheckButton"..idx);
	local ButtonText = getglobal("SKMap_ReportFrameCheckButton"..idx.."Text");
	ButtonText:SetText(SKM_UI_STRINGS.Report_Button_UseAssist);
	MyButton.tooltipText = SKM_UI_STRINGS.Report_Tooltip_UseAssist;

	local checked;
	local bValue = SkM_GetOption("AssistKillStat");
	if (bValue) then
		checked = 1;
	else
		checked = 0;
	end

	MyButton:SetChecked(checked);

	--SkM_ComputeStatistics();
	--SKMap_Report_LoadBook(SKM_CurrentBook);
end


function SKMap_Book_PrevPage()
	local FName = "SKMap_Book_PrevPage";

	if (not SKM_BookCurPage) or (not SKM_BookPages) then
		return;
	end

	local iPages = table.getn(SKM_BookPages);

	if (iPages < 1) then
		return;
	end

	if (SKM_BookCurPage > 1) then
		SKM_BookCurPage = SKM_BookCurPage - 1;
	end

	SKMap_Book_ShowCurrentPage();
end


function SKMap_Book_NextPage()
	local FName = "SKMap_Book_NextPage";

	if (not SKM_BookCurPage) or (not SKM_BookPages) then
		return;
	end

	local iPages = table.getn(SKM_BookPages);

	if (iPages < 1) then
		return;
	end

	if (SKM_BookCurPage < iPages) then
		SKM_BookCurPage = SKM_BookCurPage + 1;
	end

	SKMap_Book_ShowCurrentPage();
end


function SKMap_Book_HidePage()
	local FName = "SKMap_Book_HidePage";

	SKMap_ReportFrame_PrevPageButton:Hide();
	SKMap_ReportFrame_NextPageButton:Hide();
	SKMap_ReportFrame_PageText:Hide();

	local i;
	for i=1, SKM_BOOKFRAME_ROWS, 1 do
		local ButtonText = getglobal("SKMap_ReportFrameBookButton"..i.."Text");
		if (ButtonText) then
			ButtonText:SetText("");
		end

		local j;
		for j=1, SKM_BOOKFRAME_COLUMNS, 1 do
			local ButtonCol = getglobal("SKMap_ReportFrameBookButton"..i.."Col"..j);
			if (ButtonCol) then
				ButtonCol:SetText("");
			end
		end
	end

end


function SKMap_Book_ShowCurrentPage()
	local FName = "SKMap_Book_ShowCurrentPage";

	if (not SKM_BookPages) then
		SKMap_Book_HidePage();
		return;
	end

	local iPages = table.getn(SKM_BookPages);
	if (iPages < 1) then
		SKMap_Book_HidePage();
		return;
	end

	local sPageText = "";

	if (not SKM_BookCurPage) then
		SKM_BookCurPage = 1;
	elseif (SKM_BookCurPage > iPages) then
		SKM_BookCurPage = iPages;
	end

	sPageText = SKM_UI_STRINGS.Book_Page.." "..SKM_BookCurPage.." / "..iPages;

	if (SKM_BookCurPage == 1) then
		SKMap_ReportFrame_PrevPageButton:Disable();
	else
		SKMap_ReportFrame_PrevPageButton:Enable();
	end

	if (SKM_BookCurPage == iPages) then
		SKMap_ReportFrame_NextPageButton:Disable();
	else
		SKMap_ReportFrame_NextPageButton:Enable();
	end

	SKMap_ReportFrame_PageText:SetText(sPageText);

	SKMap_ReportFrame_PrevPageButton:Show();
	SKMap_ReportFrame_NextPageButton:Show();
	SKMap_ReportFrame_PageText:Show();

	SKMap_Report_WriteBook(SKM_BookPages[SKM_BookCurPage]);
end


function SKMap_BuildBook(p_BookHeader, p_BookText)
	local FName = "SKMap_BuildBook";

	SKM_BookPages = { };

	local iHeaderLn = 0;
	if (p_BookHeader) then
		SkM_Trace(FName, 3, "Book Header not nil : "..getn(p_BookHeader));
		iHeaderLn = getn(p_BookHeader);
	end

	local iTextLn = 0;
	if (p_BookText) then
		SkM_Trace(FName, 3, "Book Text not nil : "..getn(p_BookText));
		iTextLn = getn(p_BookText);
	end

	if (iHeaderLn >= SKM_BOOKFRAME_ROWS) then
		SkM_Trace(FName, 1, "Too many header lines : "..iHeaderLn..", Book rows = "..SKM_BOOKFRAME_ROWS);
		return;
	end

	SkM_Trace(FName, 3, "Header lines = "..iHeaderLn..", Text lines = "..iTextLn);

	local CurrentPage = { };
	local i, j;

	if (iTextLn > 0) then

		for i=1, iTextLn, 1 do
			local CurrentLine = p_BookText[i];

			if (table.getn(CurrentPage) == 0) then
				if (iHeaderLn > 0) then

					-- beginning a new page : write header
					for j=1, iHeaderLn, 1 do
						table.insert(CurrentPage, p_BookHeader[j]);
					end
				end
			end

			if ( (type(CurrentLine) == "string") or (type(CurrentLine) == "number") ) then
				-- basic line, insert it as is
				table.insert(CurrentPage, CurrentLine);

			elseif (type(CurrentLine) == "table" ) then
				if (CurrentLine.Type == nil) then
					-- table with no type specified, it is a list of columns
					-- insert it as is
					table.insert(CurrentPage, CurrentLine);

				else
					if (CurrentLine.Type == "Line") then
						-- standard line or list of columns, insert value as is
						table.insert(CurrentPage, CurrentLine.Value);

					elseif (CurrentLine.Type == "NextPage") then
						-- directive specifying to start the following page
						table.insert(SKM_BookPages, CurrentPage);
						CurrentPage = { };

					elseif (CurrentLine.Type == "MultiLine") then
						-- directive specifying a group of undivisible lines,
						-- check if there's enough space on current page
						local iNbLines = CurrentLine.Value;
						if (table.getn(CurrentPage) + iNbLines > SKM_BOOKFRAME_ROWS) then
							table.insert(SKM_BookPages, CurrentPage);
							CurrentPage = { };
						end

					else
						-- unknown case, skip
						SkM_Trace(FName, 1, "Unknown type : "..snil(CurrentLine.Type));
					end

				end
			end

			if (table.getn(CurrentPage) == SKM_BOOKFRAME_ROWS) then
				table.insert(SKM_BookPages, CurrentPage);
				CurrentPage = { };
			end

		end

	else
		if (iHeaderLn > 0) then
			-- text empty, but there is a header : create a single page with the header
			for j=1, iHeaderLn, 1 do
				table.insert(CurrentPage, p_BookHeader[j]);
			end
		end

	end

	-- insert last page
	if (table.getn(CurrentPage) > 0) then
		table.insert(SKM_BookPages, CurrentPage);
		CurrentPage = { };
	end

	if (table.getn(SKM_BookPages) > 0) then
		SKM_BookCurPage = 1;
	else
		SKM_BookCurPage = 0;
	end

end


function SKMap_Report_LoadBook(sBookType)
	local FName = "SKMap_Report_LoadBook";


	SkM_Trace(FName, 2, "Loading book type = "..snil(sBookType));

	SKM_CurrentBook = sBookType;

	if (sBookType == _SKM._bookCredits) then
		SKMap_BuildBook(nil, SKMAP_CREDITS);

	elseif (sBookType == _SKM._bookGeneralStat) then
		SKMap_BuildBook_GeneralStat();

	elseif (sBookType == _SKM._bookClassStat) then
		SKMap_BuildBook_CategoryStat("ClassList", SKM_UI_STRINGS.Book_ClassStat_Header, SKM_UI_STRINGS.Book_Label_Class);

	elseif (sBookType == _SKM._bookRaceStat) then
		SKMap_BuildBook_CategoryStat("RaceList", SKM_UI_STRINGS.Book_RaceStat_Header, SKM_UI_STRINGS.Book_Label_Race);

	elseif (sBookType == _SKM._bookPlayerStat) then
		SKMap_BuildBook_CategoryStat("EnemyList", SKM_UI_STRINGS.Book_EnemyStat_Header, SKM_UI_STRINGS.Book_Label_Enemy);

	elseif (sBookType == _SKM._bookGuildStat) then
		SKMap_BuildBook_CategoryStat("GuildList", SKM_UI_STRINGS.Book_GuildStat_Header, SKM_UI_STRINGS.Book_Label_Guild);

	elseif (sBookType == _SKM._bookMapStat) then
		SKMap_BuildBook_CategoryStat("ZoneList", SKM_UI_STRINGS.Book_ZoneStat_Header, SKM_UI_STRINGS.Book_Label_Zone);

	elseif (sBookType == _SKM._bookDateStat) then
		SKMap_BuildBook_CategoryStat("DateList", SKM_UI_STRINGS.Book_DateStat_Header, SKM_UI_STRINGS.Book_Label_Date);

	elseif (sBookType == _SKM._bookBGDateStat) then
		SKMap_BuildBook_CategoryStat("BGDateList", SKM_UI_STRINGS.Book_BGDateStat_Header, SKM_UI_STRINGS.Book_Label_Date);

	elseif (sBookType == _SKM._bookBGMapStat) then
		SKMap_BuildBook_CategoryStat("BGZoneList", SKM_UI_STRINGS.Book_BGZoneStat_Header, SKM_UI_STRINGS.Book_Label_Zone);

	elseif (sBookType == _SKM._bookBGDateMapStat) then
		SKMap_BuildBook_CategoryStat("BGDateZoneList", SKM_UI_STRINGS.Book_BGDateZoneStat_Header, SKM_UI_STRINGS.Book_Label_DateZone);

	else
		SkM_Trace(FName, 1, "Unknown book type");
		SKM_CurrentBook = nil;
		SKMap_BuildBook(nil, nil);
	end

	SKMap_Book_ShowCurrentPage();
end


function SKMap_BuildBook_GeneralStat()
	local FName = "SKMap_BuildBook_GeneralStat";

	-- recompute statistics to be sure they're up to date
	SkM_ComputeStatistics();

	-- preparing header
	local BookHeader = { };
	table.insert(BookHeader, SKM_UI_STRINGS.Book_GeneralStat_Header);
	table.insert(BookHeader, "");
	table.insert(BookHeader, SKM_BOOK_SEPARATOR);
	table.insert(BookHeader, "");

	-- book content
	local BookText = { };

	local iKill = ifnil(SKM_Context.Statistics.Globals.Kill, 0);
	local iDeath = ifnil(SKM_Context.Statistics.Globals.Death, 0);
	local sRatio;
	if (iDeath + iKill > 0) then
		sRatio = math.floor( 100 * iKill / (iDeath + iKill) ) .. " %";
	end

	local Line = { SKM_UI_STRINGS.Book_TotalKill, iKill };
	table.insert(BookText, Line);

	local Line = { SKM_UI_STRINGS.Book_TotalDeath, iDeath };
	table.insert(BookText, Line);

	table.insert(BookText, "");

	local Line = { SKM_UI_STRINGS.Book_TotalRatio, sRatio };
	table.insert(BookText, Line);

	table.insert(BookText, "");

	local Line = { SKM_UI_STRINGS.Book_AverageKillLevel, SKM_Context.Statistics.Globals.KillAverageLevel };
	table.insert(BookText, Line);

	local Line = { SKM_UI_STRINGS.Book_AverageDeathLevel, SKM_Context.Statistics.Globals.DeathAverageLevel };
	table.insert(BookText, Line);

	table.insert(BookText, "");

	local Line = { SKM_UI_STRINGS.Book_EnemyPlayers, SKM_Context.Statistics.Globals.EnemyPlayers };
	table.insert(BookText, Line);

	local Line = { SKM_UI_STRINGS.Book_EnemyGuilds, SKM_Context.Statistics.Globals.EnemyGuilds };
	table.insert(BookText, Line);

	table.insert(BookText, "");

	local Line = { SKM_UI_STRINGS.Book_MapRecords, SKM_Context.Statistics.Globals.MapRecords };
	table.insert(BookText, Line);

	SKMap_BuildBook(BookHeader, BookText);
end


function SKMap_BuildBook_EnemyStat()
	local FName = "SKMap_BuildBook_EnemyStat";

	-- recompute statistics to be sure they're up to date
	SkM_ComputeStatistics();

	-- preparing header
	local BookHeader = { };
	table.insert(BookHeader, SKM_UI_STRINGS.Book_EnemyStat_Header);
	table.insert(BookHeader, "");

	local sLine = { SKM_UI_STRINGS.Book_Label_Enemy, SKM_UI_STRINGS.Book_Label_Kill, SKM_UI_STRINGS.Book_Label_Death, SKM_UI_STRINGS.Book_Label_Ratio };
	table.insert(BookHeader, sLine);

	table.insert(BookHeader, SKM_BOOK_SEPARATOR);
	table.insert(BookHeader, "");


	-- book content
	local BookText = { };

	local  val;
	local i;
	for i=1, getn(SKM_Context.Statistics.EnemyList), 1 do
		val = SKM_Context.Statistics.EnemyList[i];
		local sEnemy = val.Key;
		local iDeath = val.Death;
		local iKill = val.Kill;

		local sRatio;
		if (iDeath + iKill > 0) then
			sRatio = math.floor( 100 * iKill / (iDeath + iKill) ) .. " %";
		end

		local Line = { sRace, iKill, iDeath, sRatio };

		table.insert(BookText, Line);
	end

	if (getn(BookText) == 0) then
		table.insert(BookText, SKM_UI_STRINGS.Book_NoData);
	end

	SKMap_BuildBook(BookHeader, BookText);
end


function SKMap_BuildBook_CategoryStat(sCategory, sTitle, sLabel)
	local FName = "SKMap_BuildBook_CategoryStat";

	-- recompute statistics to be sure they're up to date
	SkM_ComputeStatistics();

	-- preparing header
	local BookHeader = { };
	table.insert(BookHeader, sTitle);
	table.insert(BookHeader, "");

	local sLine = { sLabel, SKM_UI_STRINGS.Book_Label_Kill, SKM_UI_STRINGS.Book_Label_Death, SKM_UI_STRINGS.Book_Label_Ratio };
	table.insert(BookHeader, sLine);

	table.insert(BookHeader, SKM_BOOK_SEPARATOR);
	table.insert(BookHeader, "");



	-- book content
	local BookText = { };

	local  val;
	local i;
	for i=1, getn(SKM_Context.Statistics[sCategory]), 1 do
		val = SKM_Context.Statistics[sCategory][i];
		local sElem = val.Key;

		local iDeath = val.Death;
		local iKill = val.Kill;

		local sRatio;
		if (iDeath + iKill > 0) then
			sRatio = math.floor( 100 * iKill / (iDeath + iKill) ) .. " %";
		end

		local Line = { sElem, iKill, iDeath, sRatio };

		table.insert(BookText, Line);
	end

	if (getn(BookText) == 0) then
		table.insert(BookText, SKM_UI_STRINGS.Book_NoData);
	end

	SKMap_BuildBook(BookHeader, BookText);
end


function SKMap_ReportButton_OnClick()

	if (SKM_List_ActiveList == _SKM._players) then

		if (SKM_List_SelectedPlayer ~= nil) then
			SKMap_Report_EnemyRecords(SKM_List_SelectedPlayer);
			SKMap_ToggleUI("SKMap_ReportFrame");
		end

	elseif (SKM_List_ActiveList == _SKM._guilds) then

		if (SKM_List_SelectedGuild ~= nil) then
			SKMap_Report_EnemyGuildRecords(SKM_List_SelectedGuild);
			SKMap_ToggleUI("SKMap_ReportFrame");
		end
	end

end


function SKMap_Report_EnemyRecords(sName)
	local FName = "SKMap_Report_EnemyRecords";

	SKM_CurrentBook = nil;

	-- preparing header
	local BookHeader = { };
	table.insert(BookHeader, string.format("%s vs %s", _PlayerName, sName));
	table.insert(BookHeader, "");
	table.insert(BookHeader, SKM_BOOK_SEPARATOR);
	table.insert(BookHeader, "");

	-- book content
	local BookText = { };

	local i;

	local iNbNotes = table.getn(SKM_Data[_RealmName][_PlayerName].GlobalMapData);
	for i=iNbNotes, 1, -1 do
		local Note = SKM_Data[_RealmName][_PlayerName].GlobalMapData[i];

		local StoredInfo = Note[_SKM._storedInfo];

		if (StoredInfo) and (StoredInfo[_SKM._name] == sName) then

			if   (StoredInfo[_SKM._type] == _SKM._playerKill)
			  or (StoredInfo[_SKM._type] == _SKM._playerFullKill)
			  or (StoredInfo[_SKM._type] == _SKM._playerAssistKill and SkM_GetOption("AssistKillStat"))
			  or (StoredInfo[_SKM._type] == _SKM._playerDeathPvP)
			then
				table.insert(BookText, {Type = "MultiLine", Value = 3 } );

				--local sZoneText = SKM_Context.Zones[Note[_SKM._continent]][Note[_SKM._zone]];
				local sZoneText = SkM_GetZoneTextFromIndex(Note[_SKM._continent], Note[_SKM._zone]);
				local sDate = StoredInfo[_SKM._date];
				table.insert(BookText, sDate.." - "..sZoneText);

				local sLine;
				if (StoredInfo[_SKM._type] == _SKM._playerAssistKill) then
					sLine = string.format(SKM_UI_STRINGS.Book_Format_AssistKill, sName);
				elseif (StoredInfo[_SKM._type] == _SKM._playerKill) then
					sLine = string.format(SKM_UI_STRINGS.Book_Format_Kill, sName);
				elseif (StoredInfo[_SKM._type] == _SKM._playerFullKill) then
					if (StoredInfo[_SKM._loneWolfKill]) then
						sLine = string.format(SKM_UI_STRINGS.Book_Format_LoneWolfKill, sName);
					else
						sLine = string.format(SKM_UI_STRINGS.Book_Format_FullKill, sName);
					end
				elseif (StoredInfo[_SKM._type] == _SKM._playerDeathPvP) then
					sLine = string.format(SKM_UI_STRINGS.Book_Format_Death, sName);
				end
				table.insert(BookText, sLine);

				table.insert(BookText, "");
			end

		end
	end

	if (getn(BookText) == 0) then
		table.insert(BookText, SKM_UI_STRINGS.Book_NoData);
	end

	SKMap_BuildBook(BookHeader, BookText);

	SKMap_Book_ShowCurrentPage();
end


function SKMap_Report_EnemyGuildRecords(sGuildName)
	local FName = "SKMap_Report_EnemyGuildRecords";

	SKM_CurrentBook = nil;

	-- preparing header
	local BookHeader = { };

	table.insert(BookHeader, string.format("%s vs <%s>", _PlayerName, sGuildName));
	table.insert(BookHeader, "");
	table.insert(BookHeader, SKM_BOOK_SEPARATOR);
	table.insert(BookHeader, "");

	-- book content
	local BookText = { };

	local i;
	local iNbNotes = table.getn(SKM_Data[_RealmName][_PlayerName].GlobalMapData);
	for i=iNbNotes, 1, -1 do
		local Note = SKM_Data[_RealmName][_PlayerName].GlobalMapData[i];

		local StoredInfo = Note[_SKM._storedInfo];

		local sName;
		local Enemy;
		local sPlayerGuild;

		if (StoredInfo) then
			sName = StoredInfo[_SKM._name];
		end

		if (sName) then
			Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[sName];
			if (Enemy) then
				sPlayerGuild = Enemy[_SKM._guild];
			end
		end

		if (sPlayerGuild == sGuildName) then

			if   (StoredInfo[_SKM._type] == _SKM._playerKill)
			  or (StoredInfo[_SKM._type] == _SKM._playerFullKill)
			-- or (StoredInfo[_SKM._type] == _SKM._playerAssistKill)
			  or (StoredInfo[_SKM._type] == _SKM._playerDeathPvP)
			then
				table.insert(BookText, {Type = "MultiLine", Value = 3 } );

				--local sZoneText = SKM_Context.Zones[Note[_SKM._continent]][Note[_SKM._zone]];
				local sZoneText = SkM_GetZoneTextFromIndex(Note[_SKM._continent], Note[_SKM._zone]);
				local sDate = StoredInfo[_SKM._date];
				table.insert(BookText, sDate.." - "..sZoneText);

				local sLine;
				if (StoredInfo[_SKM._type] == _SKM._playerKill) then
					sLine = string.format(SKM_UI_STRINGS.Book_Format_Kill, sName);
				elseif (StoredInfo[_SKM._type] == _SKM._playerFullKill) then
					if (StoredInfo[_SKM._loneWolfKill]) then
						sLine = string.format(SKM_UI_STRINGS.Book_Format_LoneWolfKill, sName);
					else
						sLine = string.format(SKM_UI_STRINGS.Book_Format_FullKill, sName);
					end
				elseif (StoredInfo[_SKM._type] == _SKM._playerDeathPvP) then
					sLine = string.format(SKM_UI_STRINGS.Book_Format_Death, sName);
				end
				table.insert(BookText, sLine);

				table.insert(BookText, "");
			end

		end
	end

	if (getn(BookText) == 0) then
		table.insert(BookText, SKM_UI_STRINGS.Book_NoData);
	end

	SKMap_BuildBook(BookHeader, BookText);

	SKMap_Book_ShowCurrentPage();
end


function SKMap_DeleteButton_Accept(ActiveList, sName)
	local FName = "SKMap_DeleteButton_Accept";

	SkM_Trace(FName, 2, "Delete confirmed : list = "..snil(ActiveList)..", Name = "..snil(sName));

	if (sName ~= nil) then

		if (ActiveList == _SKM._players) then
			SkM_DeleteEnemy(sName);

			if (SKM_List_SelectedPlayer == sName) then
				SKM_List_SelectedPlayer = nil;
				if (SKM_List_ActiveList == _SKM._players) then
					SKMap_ListFrame_ClearDetail();
				end
			end
		end

		SKMap_ListFrame_Load();
	end

	SKM_ActivePopup = false;
end


function SKMap_DeleteButton_Cancel()
	SKM_ActivePopup = false;
end


function SKMap_DeleteButton_OnClick()
	local FName = "SKMap_DeleteButton_OnClick";

	SkM_Trace(FName, 1, "Delete requested");

	if (SKM_ActivePopup) then
		return;
	end

	local sName;
	local ActiveList = SKM_List_ActiveList;

	if (SKM_List_ActiveList == _SKM._players) then
		sName = SKM_List_SelectedPlayer;
	end

	if (sName == nil) then
		return;
	end

	local sPlayerColor = SKM_Config.Col_LabelTitle;
	local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[SKM_List_SelectedPlayer];
	if (Enemy) and (Enemy[_SKM._atWar]) then
		sPlayerColor = SKM_Config.Col_PlayerWar;
	end

	local dialogdef = StaticPopupDialogs["SKMAP_CONFIRM"];

	dialogdef.text  = string.format(SKM_UI_STRINGS.List_ConfirmDeletePlayer, SKM_Config.Col_Label, sPlayerColor, sName, SKM_Config.Col_Label);

	--dialogdef.OnAccept = function() SKMap_DeleteButton_Accept(SKM_List_ActiveList, sName) end;
	dialogdef.OnAccept = function() SKMap_DeleteButton_Accept(ActiveList, sName) end;

	SKM_ActivePopup = true;
	StaticPopup_Show("SKMAP_CONFIRM");
end


function SKMap_EditBox_Accept()
	local FName = "SKMap_EditBox_Accept";

	SkM_Trace(FName, 1, "Edit accepted");

	local MyEditBox = getglobal(this:GetParent():GetName().."EditBox");
	if (MyEditBox) then
		local sValue = MyEditBox:GetText();

		SkM_Trace(FName, 2, "Value : "..snil(sValue));

		local sName = SKM_EditNoteContext.Element;

		if (SKM_EditNoteContext.List == _SKM._players) then
			SKM_Data[_RealmName][_PlayerName].EnemyHistory[sName][_SKM._playerNote] = sValue;
		elseif (SKM_EditNoteContext.List == _SKM._guilds) then
			SKM_Data[_RealmName][_PlayerName].GuildHistory[sName][_SKM._playerNote] = sValue;
		elseif (SKM_EditNoteContext.List == _SKM._duels) then
			SKM_Data[_RealmName][_PlayerName].DuelHistory[sName][_SKM._playerNote] = sValue;
		end

	end

	local bVisible, sFrame = SKMap_IsUIVisible();

	if (sFrame == "SKMap_ListFrame") and (SKM_List_ActiveList == SKM_EditNoteContext.List) then
	--if (SKM_List_ActiveList == SKM_EditNoteContext.List) then

		if (SKM_EditNoteContext.List == _SKM._players) and (SKM_EditNoteContext.Element == SKM_List_SelectedPlayer) then
			SKMap_ListFrame_SelectElement(SKM_EditNoteContext.Element);
		elseif (SKM_EditNoteContext.List == _SKM._guilds) and (SKM_EditNoteContext.Element == SKM_List_SelectedGuild) then

			SKMap_ListFrame_SelectGuild(SKM_EditNoteContext.Element);
		end

	elseif (sFrame == "SKMap_DuelFrame") then
		SKMap_DuelFrame_SelectElement(SKM_EditNoteContext.Element);
	end

	SKM_EditNoteContext = { };


	SKMapStaticPopupEdit:Hide();
	SKM_ActivePopup = false;
end

function SKMap_EditBox_Cancel()
	local FName = "SKMap_EditBox_Cancel";

	SkM_Trace(FName, 1, "Edit canceled");

	SKMapStaticPopupEdit:Hide();
	SKM_ActivePopup = false;
end


function SKMap_EditBox_Clear()
	local sPopupEdit = "SKMapStaticPopupEdit";
	local MyEditBox = getglobal(sPopupEdit.."EditBox");
	MyEditBox:SetText("");
end


function SKMap_EditBox_OnShow()
	local FName = "SKMap_EditBox_OnShow";

	SkM_Trace(FName, 3, "OnShow");

	getglobal(this:GetName().."EditBox"):SetFocus();
end


function SKMap_EditNote()
	local FName = "SKMap_EditNote";

	SkM_Trace(FName, 1, "Edit Note");

	if (SKM_ActivePopup) then
		return;
	end

	local sPopupEdit = "SKMapStaticPopupEdit";
	local MyEditBox = getglobal(sPopupEdit.."EditBox");
	local MyTitle = getglobal(sPopupEdit.."Title");
	local MyPrompt = getglobal(sPopupEdit.."Prompt");

	MyTitle:SetText(SKM_UI_STRINGS.List_EditNote_Title);

	local bVisible, sFrame = SKMap_IsUIVisible();

	if (sFrame == "SKMap_ListFrame") then

		if (SKM_List_ActiveList == _SKM._players) then
			if (SKM_List_SelectedPlayer == nil) then
				SkM_Trace(FName, 2, "No selected player !");
				return;
			end

			local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[SKM_List_SelectedPlayer];
			if (Enemy == nil) then
				SkM_Trace(FName, 2, "Enemy not found : "..snil(SKM_List_SelectedPlayer));
				return;
			end

			local sPlayerColor = SKM_Config.Col_LabelTitle;
			if (Enemy) and (Enemy[_SKM._atWar]) then
				sPlayerColor = SKM_Config.Col_PlayerWar;
			end

			MyPrompt:SetText(string.format(SKM_UI_STRINGS.List_EditPlayerNote_Prompt, SKM_Config.Col_Label, sPlayerColor, SKM_List_SelectedPlayer, SKM_Config.Col_Label));

			MyEditBox:SetText(ifnil(Enemy[_SKM._playerNote], ""));

			SKM_EditNoteContext = { List = _SKM._players, Element = SKM_List_SelectedPlayer };

			SKM_ActivePopup = true;
			SKMapStaticPopupEdit:Show();

		elseif (SKM_List_ActiveList == _SKM._guilds) then
			if (SKM_List_SelectedGuild == nil) then
				return;
			end

			local Guild = SKM_Data[_RealmName][_PlayerName].GuildHistory[SKM_List_SelectedGuild];
			if (Guild == nil) then
				return;
			end

			local sGuildColor = SKM_Config.Col_LabelTitle;
			if (Guild) and (Guild[_SKM._atWar]) then
				sGuildColor = SKM_Config.Col_PlayerWar;
			end

			MyPrompt:SetText(string.format(SKM_UI_STRINGS.List_EditGuildNote_Prompt, SKM_Config.Col_Label, sGuildColor, SKM_List_SelectedGuild, SKM_Config.Col_Label));

			MyEditBox:SetText(ifnil(Guild[_SKM._playerNote], ""));

			SKM_EditNoteContext = { List = _SKM._guilds, Element = SKM_List_SelectedGuild };

			SKM_ActivePopup = true;
			SKMapStaticPopupEdit:Show();
		end

	elseif (sFrame == "SKMap_DuelFrame") then

		if (SKM_DuelList_SelectedPlayer == nil) then
			SkM_Trace(FName, 2, "No selected player !");
			return;
		end

		local Enemy = SKM_Data[_RealmName][_PlayerName].DuelHistory[SKM_DuelList_SelectedPlayer];
		if (Enemy == nil) then
			SkM_Trace(FName, 2, "Enemy not found : "..snil(SKM_DuelList_SelectedPlayer));
			return;
		end

		local sPlayerColor = SKM_Config.Col_LabelTitle;

		MyPrompt:SetText(string.format(SKM_UI_STRINGS.List_EditPlayerNote_Prompt, SKM_Config.Col_Label, sPlayerColor, SKM_DuelList_SelectedPlayer, SKM_Config.Col_Label));

		MyEditBox:SetText(ifnil(Enemy[_SKM._playerNote], ""));

		SKM_EditNoteContext = { List = _SKM._duels, Element = SKM_DuelList_SelectedPlayer };

		SKM_ActivePopup = true;
		SKMapStaticPopupEdit:Show();
	end

end


function SKMap_WorldControlHide_OnClick()
	local FName = "SKMap_WorldControlHide_OnClick";

	SkM_SetOption("ShowWorldMapControl", false);
	SKMapWorldMapControl:Hide();
end


function SKMap_WorldControlShowRecords_OnClick()
	local FName = "SKMap_WorldControlShowRecords_OnClick";

	local idx=1;
	local MyButton = getglobal("SKMapWorldMapControl_CheckButton"..idx);

	if (not MyButton:GetChecked()) then
		SkM_SetOption("MapDisplayRecords", false);
	else
		SkM_SetOption("MapDisplayRecords", true);
	end

	SkM_MainDraw();
end




function SKMap_IsUIVisible()
	local bVisible = false;
	local sSubFrame = nil;

	if (SKMapFrame:IsVisible()) then
		bVisible = true;

		for idx, val in SKM_TAB_SUBFRAMES do
			local tabFrame = getglobal(val);
			if (tabFrame:IsVisible()) then
				sSubFrame = val;
			end
		end
	end

	return bVisible, sSubFrame;
end


function SKMap_DuelFrame_Load()
	local FName = "SKMap_DuelFrame_Load";

	SkM_Trace(FName, 1, "Loading DuelFrame");

	SKMap_SetDuelListContent();
	SKMap_DuelFrame_UpdateList();
	SKMap_DuelFrame_SortList();

end


function SKMap_SetDuelListContent()
	local FName = "SKMap_SetDuelListContent";

	SKM_DuelList_Content = { };

	local idx, val;
	for idx, val in  SKM_Data[_RealmName][_PlayerName].DuelHistory do
		local Elem = copytable(val);

		Elem[_SKM._class] = SkM_GetClassText(Elem[_SKM._class]);
		Elem[_SKM._race] = SkM_GetRaceText(Elem[_SKM._race]);

		if (Elem[_SKM._duel]) then
			Elem[_SKM._score] = math.floor(100 * 100 * ifnil(Elem[_SKM._win], 0)/Elem[_SKM._duel]) / 100;
		end
		table.insert(SKM_DuelList_Content, Elem);
	end

end


function SKMap_DuelFrame_UpdateList()
	local FName = "SKMap_DuelFrame_UpdateList";

	local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_DuelScrollFrame);

	SkM_Trace(FName, 4, "Scrollbar offset = "..snil(iScrollOffset));

	local iEnemyCount = table.getn(SKM_DuelList_Content);
	SkM_Trace(FName, 4, "Enemy Count = "..snil(iEnemyCount));

	local iEnemyIndex = iScrollOffset + 1;

	SkM_Trace(FName, 4, "Enemy Index = "..snil(iEnemyIndex));

	local i;
	for i=1, SKM_DUELFRAME_ROWS, 1 do
		local RowButton = getglobal("SKMap_DuelFrameButton"..i);

		if (iEnemyIndex <= iEnemyCount) then

			RowButtonName = getglobal("SKMap_DuelFrameButton"..i.."Name");
			RowButtonGuild = getglobal("SKMap_DuelFrameButton"..i.."Guild");
			RowButtonLevel = getglobal("SKMap_DuelFrameButton"..i.."Level");
			RowButtonRace = getglobal("SKMap_DuelFrameButton"..i.."Race");
			RowButtonClass = getglobal("SKMap_DuelFrameButton"..i.."Class");

			RowButtonWin = getglobal("SKMap_DuelFrameButton"..i.."Win");
			RowButtonLoss = getglobal("SKMap_DuelFrameButton"..i.."Loss");
			RowButtonDuel = getglobal("SKMap_DuelFrameButton"..i.."Duel");
			RowButtonLastDuel = getglobal("SKMap_DuelFrameButton"..i.."LastDuel");
			RowButtonScore = getglobal("SKMap_DuelFrameButton"..i.."Score");

			local sName = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._name], "??");
			local sLevel = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._level], "??");
			local sRace = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._race], "??");
			local sClass = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._class], "??");
			local sLastDuel = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._lastDuel], "??");


			local sGuild = SKM_DuelList_Content[iEnemyIndex][_SKM._guild];

			local iWin = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._win], 0);
			local iLoss = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._loss], 0);

			local iDuel = ifnil(SKM_DuelList_Content[iEnemyIndex][_SKM._duel], 0);

			if (sLevel == -1) then
				sLevel = "++";
			end

			local iScore = SKM_DuelList_Content[iEnemyIndex][_SKM._score];

			RowButtonName:SetText(sName);
			RowButtonGuild:SetText(sGuild);
			RowButtonLevel:SetText(sLevel);
			RowButtonRace:SetText(sRace);
			RowButtonClass:SetText(sClass);
			RowButtonWin:SetText(iWin);
			RowButtonLoss:SetText(iLoss);
			RowButtonDuel:SetText(iDuel);
			RowButtonLastDuel:SetText(sLastDuel);
			RowButtonScore:SetText(iScore);

			RowButton:Show();

			iEnemyIndex = iEnemyIndex + 1;
		else
			RowButton:Hide();
		end
	end

	FauxScrollFrame_Update(SKMap_DuelScrollFrame, iEnemyCount, SKM_DUELFRAME_ROWS, SKM_DUELFRAME_ROWHEIGHT);
end


function SKMap_DuelFrame_SortList(sSortType)
	local FName = "SKMap_DuelFrame_SortList";

	if (sSortType) then
		--if (sSortType == SKM_DuelList_SortType) then
		if (sSortType == SkM_GetOption("DuelList_SortType") ) then
			--if (SKM_DuelList_ReverseSort) then
			if ( SkM_GetOption("DuelList_ReverseSort") ) then
				--SKM_DuelList_ReverseSort = false;
				SkM_SetOption("DuelList_ReverseSort", false);
			else
				--SKM_DuelList_ReverseSort = true;
				SkM_SetOption("DuelList_ReverseSort", true);
			end
		else
			--SKM_DuelList_SortType = sSortType;
			SkM_SetOption("DuelList_SortType", sSortType);

			--SKM_DuelList_SortTypes = removefromlist(sSortType, SKM_DuelList_SortTypes);
			SKM_Settings.DuelList_SortTypes = removefromlist(sSortType, SkM_GetOption("DuelList_SortTypes") );
			--table.insert(SKM_DuelList_SortTypes, 1, sSortType);
			table.insert(SKM_Settings.DuelList_SortTypes, 1, sSortType);
		end
	end

	if (SKM_DuelList_Content) then
		table.sort(SKM_DuelList_Content, SKMap_DuelFrame_Sort);
	end

	SKMap_DuelFrame_UpdateList();
end



function SKMap_DuelFrame_Sort(e1, e2)
	local FName = "SKMap_DuelFrame_Sort";

	SkM_Trace(FName, 4, "Begin");

	if (e1 == nil) then
		if (e2 == nil) then
			return false;
		else
			return true;
		end
	elseif (e2 == nil) then
		return false;
	end

	--local iSortTypes = table.getn(SKM_DuelList_SortTypes);
	local iSortTypes = table.getn( SkM_GetOption("DuelList_SortTypes") );

	local i;
	for i=1, iSortTypes, 1 do
		local bReverseSort = false;
		--if (i == 1) and (SKM_DuelList_ReverseSort == true) then
		if (i == 1) and ( SkM_GetOption("DuelList_ReverseSort") ) then
			bReverseSort = true;
		end
		--local bCmp = SKMap_ListFrame_SubSort(e1, e2, SKM_DuelList_SortTypes[i], bReverseSort);
		local bCmp = SKMap_ListFrame_SubSort(e1, e2, SkM_GetOption("DuelList_SortTypes")[i], bReverseSort);
		if (bCmp ~= nil) then
			return bCmp;
		end
	end
	return false;

end


function SKMap_DuelFrame_SelectElement(sPlayerName)
	local FName = "SKMap_DuelFrame_SelectElement";

	local sName;

	if (sPlayerName ~= nil) then
		sName = sPlayerName;
	else
		local id = this:GetID();
		local iScrollOffset = FauxScrollFrame_GetOffset(SKMap_DuelScrollFrame);
		local iEnemyCount = table.getn(SKM_DuelList_Content);

		SkM_Trace(FName, 3, "Scroll offset = "..iScrollOffset);
		SkM_Trace(FName, 3, "Line id = "..id);

		local iEnemyIndex = iScrollOffset + id;
		SkM_Trace(FName, 3, "Enemy Index = "..iEnemyIndex);

		if (iEnemyIndex <= iEnemyCount) then
			sName = SKM_DuelList_Content[iEnemyIndex][_SKM._name];
		end

	end

	local Enemy;
	if (sName ~= nil) then
		Enemy = SKM_Data[_RealmName][_PlayerName].DuelHistory[sName];
	end

	local Lines = { };

	if (Enemy ~= nil) then
		SKM_DuelList_SelectedPlayer = sName;

		local Guild;

		local sGuild = Enemy[_SKM._guild];
		local sLevel = ifnil(Enemy[_SKM._level], "??");
		local sRace = ifnil(SkM_GetRaceText(Enemy[_SKM._race]), "??");
		local sClass = ifnil(SkM_GetClassText(Enemy[_SKM._class]), "??");
		local sLastDuel = ifnil(Enemy[_SKM._lastDuel], "??");

		local iWin = ifnil(Enemy[_SKM._win], 0);
		local iLoss = ifnil(Enemy[_SKM._loss], 0);
		local iDuel = ifnil(Enemy[_SKM._duel], 0);

		local iScore = math.floor(100 * 100 * ifnil(Enemy[_SKM._win], 0)/Enemy[_SKM._duel]) / 100;

		if (sLevel == -1) then
			sLevel = "++";
		end


		SKMap_DuelFrame_EditNote:Show();
		--SKMap_DuelFrame_ReportButton:Show();
		SKMap_DuelFrame_DeleteButton:Show();


		-- line 1 : player name
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Player;
		sLine = sLine..SKM_Config.Col_Label;
		sLine = sLine..sName..SKM_Config.Col_Label;


		table.insert(Lines, sLine);


		-- line 2 (optional) : player guild
		if (sGuild ~= nil) and (sGuild ~= "") then

			local sLine = "";
			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Guild;
			sLine = sLine..SKM_Config.Col_Label;
			sLine = sLine..sGuild..SKM_Config.Col_Label;

			table.insert(Lines, sLine);
		end


		-- line 3 (optional, not shown if info not available) : level race class
		if (Enemy[_SKM._level] ~= nil) and (Enemy[_SKM._race] ~= nil) and (Enemy[_SKM._class] ~= nil) then

			local sLine = "";
			sLine = sLine..SKM_Config.Col_Label..SKM_UI_STRINGS.List_Frame_Level..sLevel.." "..sRace.." "..sClass; -- 0.08.2 Add localization

			table.insert(Lines, sLine);
		end


		-- line 4 : last duel time
		if (Enemy[_SKM._lastDuel] ~= nil) then

			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Last_Duel;
			sLine = sLine..SKM_Config.Col_Label..Enemy[_SKM._lastDuel];

			if (Enemy[_SKM._continent] ~= nil) and (Enemy[_SKM._zone] ~= nil) then
				--local sZoneText = SKM_Context.Zones[Enemy[_SKM._continent]][Enemy[_SKM._zone]];
				local sZoneText = SkM_GetZoneTextFromIndex(Enemy[_SKM._continent], Enemy[_SKM._zone]);
				sLine = sLine.." - "..sZoneText;
			end

			table.insert(Lines, sLine);
		end


		-- line 6 : meet and death counts
		local sLine = "";

		sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Duel..SKM_Config.Col_Label..iDuel;
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Win..SKM_Config.Col_DuelWin .. iWin;
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Loss..SKM_Config.Col_DuelLoss .. iLoss;
		sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Score..SKM_Config.Col_Label .. iScore;

		table.insert(Lines, sLine);



		-- line 8 : player notes
		if (Enemy[_SKM._playerNote] ~= nil) and (Enemy[_SKM._playerNote] ~= "") then
			local sLine = "";

			sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Note; -- 0.08.2 Add localization
			sLine = sLine..SKM_Config.Col_Label..Enemy[_SKM._playerNote];

			table.insert(Lines, sLine);
		end


		local i;
		for i=1, SKM_DUELFRAME_DETAIL_ROWS, 1 do
			local ButtonText = getglobal("SKMap_DuelFrameDetailButton"..i.."Text");

			if (i <= getn(Lines)) then
				SkM_Trace(FName, 2, i.." : "..Lines[i]);

				if (ButtonText) then
					ButtonText:SetText(Lines[i]);
				end
			else
				ButtonText:SetText("");
			end
		end
	end

end


function SKMap_DuelEditNote()
	local FName = "SKMap_DuelEditNote";

	if (SKM_ActivePopup) then
		return;
	end

	local sPopupEdit = "SKMapStaticPopupEdit";
	local MyEditBox = getglobal(sPopupEdit.."EditBox");
	local MyTitle = getglobal(sPopupEdit.."Title");
	local MyPrompt = getglobal(sPopupEdit.."Prompt");

	MyTitle:SetText(SKM_UI_STRINGS.List_EditNote_Title);


	if (SKM_DuelList_SelectedPlayer == nil) then
		SkM_Trace(FName, 2, "No selected player !");
		return;
	end

	local Enemy = SKM_Data[_RealmName][_PlayerName].DuelHistory[SKM_DuelList_SelectedPlayer];
	if (Enemy == nil) then
		SkM_Trace(FName, 2, "Enemy not found : "..snil(SKM_DuelList_SelectedPlayer));
		return;
	end

	local sPlayerColor = SKM_Config.Col_LabelTitle;

	MyPrompt:SetText(string.format(SKM_UI_STRINGS.List_EditPlayerNote_Prompt, SKM_Config.Col_Label, sPlayerColor, SKM_List_SelectedPlayer, SKM_Config.Col_Label));

	MyEditBox:SetText(ifnil(Enemy[_SKM._playerNote], ""));

	SKM_EditNoteContext = { List = _SKM._duels, Element = SKM_DuelList_SelectedPlayer };

	SKM_ActivePopup = true;
	SKMapStaticPopupEdit:Show();

end


function SKMap_DeleteDuel_Accept(sName)
	local FName = "SKMap_DeleteDuel_Accept";

	SkM_Trace(FName, 2, "Delete confirmed : Name = "..snil(sName));

	if (sName ~= nil) then

		SkM_DeleteDuelEnemy(sName);

		if (SKM_DuelList_SelectedPlayer == sName) then
			SKM_DuelList_SelectedPlayer = nil;
			SKMap_DuelFrame_ClearDetail();
		end

		SKMap_DuelFrame_Load();
	end

	SKM_ActivePopup = false;
end


function SKMap_DeleteDuel_OnClick()
	local FName = "SKMap_DeleteDuel_OnClick";

	SkM_Trace(FName, 1, "Delete requested");

	if (SKM_ActivePopup) then
		return;
	end

	local sName;
	local ActiveList = SKM_List_ActiveList;

	sName = SKM_DuelList_SelectedPlayer;

	if (sName == nil) then
		return;
	end

	local sPlayerColor = SKM_Config.Col_LabelTitle;
	local Enemy = SKM_Data[_RealmName][_PlayerName].DuelHistory[SKM_DuelList_SelectedPlayer];

	local dialogdef = StaticPopupDialogs["SKMAP_CONFIRM"];

	dialogdef.text  = string.format(SKM_UI_STRINGS.Duel_ConfirmDeletePlayer, SKM_Config.Col_Label, sPlayerColor, sName, SKM_Config.Col_Label);

	dialogdef.OnAccept = function() SKMap_DeleteDuel_Accept(sName) end;

	SKM_ActivePopup = true;
	StaticPopup_Show("SKMAP_CONFIRM");
end


function SKMap_DuelFrame_ClearDetail()
	local i;
	for i=1, SKM_DUELFRAME_DETAIL_ROWS, 1 do
		local ButtonText = getglobal("SKMap_DuelFrameDetailButton"..i.."Text");
		if (ButtonText) then
			ButtonText:SetText("");
		end
	end

	SKMap_DuelFrame_EditNote:Hide();
	--SKMap_DuelFrame_ReportButton:Hide();
	SKMap_DuelFrame_DeleteButton:Hide();
end


function SKMap_ReportFrame_UseAssist()
	local FName = "SKMap_ReportFrame_UseAssist";

	local MyButton = getglobal("SKMap_ReportFrameCheckButton1");

	--SKM_Config.FilterNotAtWar = false;
	--if (MyButton:GetChecked()) then
	--	SKM_Config.FilterNotAtWar = true;
	--end

	local idx=1;
	local MyButton = getglobal("SKMap_ReportFrameCheckButton"..idx);

	if (not MyButton:GetChecked()) then
		SkM_SetOption("AssistKillStat", false);
	else
		SkM_SetOption("AssistKillStat", true);
	end

	if (SKM_CurrentBook ~= nil) then
		SKMap_Report_LoadBook(SKM_CurrentBook);

		SKMap_ReportFrame_Load();
	end
end


function SKMap_TargetFrame_OnDragStart()

	if (not SkM_GetOption("LockedTargetInfo")) then
		if (SkM_GetOption("SmallTargetInfo")) then
			SKMapSmallTargetInfoFrame:StartMoving();
		else
			SKMapTargetInfoFrame:StartMoving();
		end
	end
end


function SKMap_TargetFrame_OnDragStop()
	--TargetLogHistoryFrame:StopMovingOrSizing();

	if (SkM_GetOption("SmallTargetInfo")) then
		SKMapSmallTargetInfoFrame:StopMovingOrSizing();
	else
		SKMapTargetInfoFrame:StopMovingOrSizing();
	end
end


function SKMap_Frame_MouseUp()
	local FName = "SKMap_Frame_MouseUp";

	if ( this.isMoving ) then
		this:StopMovingOrSizing();
		this.isMoving = false;

		local frameName = this:GetName();

		if (frameName == "SKMapTargetInfoFrame" ) then
			SKMapSmallTargetInfoFrame:ClearAllPoints();
			SKMapSmallTargetInfoFrame:SetPoint("TOPLEFT","SKMapTargetInfoFrame","TOPLEFT",0,0);
		elseif (frameName == "SKMapSmallTargetInfoFrame" ) then
			SKMapTargetInfoFrame:ClearAllPoints();
			SKMapTargetInfoFrame:SetPoint("TOPLEFT","SKMapSmallTargetInfoFrame","TOPLEFT",0,0);
		end

	end
end

function SKMap_Frame_MouseDown(bLocked)
 --if ( ( ( not this.isLocked ) or ( this.isLocked == 0 ) ) and ( arg1 == "LeftButton" ) ) then
	if (not bLocked) and ( arg1 == "LeftButton" ) then
  	this:StartMoving();
  	this.isMoving = true;
	end
end

--/script SKMapTargetInfoFrame:SetPoint("TOPLEFT","TargetFrame","TOPRIGHT",-32,-52);
--/script SKMapSmallTargetInfoFrame:SetPoint("TOPLEFT","TargetFrame","TOPRIGHT",-32,-52);


function SKMap_TooltipAddLines(Lines)
	local i;
	for i=1, table.getn(Lines), 1 do
		GameTooltip:AddLine(Lines[i]);
	end

  --GameTooltip:SetHeight( GameTooltip:GetHeight() + GameTooltip:GetHeight() / GameTooltip:NumLines() );
  GameTooltip:Show();
end


function SKMap_TooltipEnemyInfo(sName)
	local FName = "SKMap_TooltipEnemyInfo";

	local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[sName];
	if (not Enemy) then
		SkM_Trace(FName, 2, "Unknown enemy : "..snil(sName));
		return false;
	end

	local iKill = ifnil(Enemy[_SKM._playerKill], 0);
	local iAssistKill = ifnil(Enemy[_SKM._playerAssistKill], 0);
	local iFullKill = ifnil(Enemy[_SKM._playerFullKill], 0);
	local iTotalKill = iKill + iAssistKill + iFullKill;
	local iDeath = ifnil(Enemy[_SKM._enemyKillPlayer], 0);
	local iMet = ifnil(Enemy[_SKM._meetCount], 0);
	local iLoneWolf = ifnil(Enemy[_SKM._loneWolfKill], 0);

	local iHonorKill = ifnil(Enemy[_SKM._honorKill], 0);
	local iRemaining = SkM_GetHonorRemainingKills(sName);

	local Lines = { };


	local sLine = "";
	sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Met..SKM_Config.Col_PlayerMet..iMet; -- 0.08.2 Add localization
	sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Death..SKM_Config.Col_PlayerDeath .. iDeath; -- 0.08.2 Add localization
	--sLine = sLine.."     "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_LoneWolf..SKM_Config.Col_LoneWolfKill .. iLoneWolf;

	table.insert(Lines, sLine);


	local sLine = "";
	sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Kill..SKM_Config.Col_PlayerTotalKill..iTotalKill;
	--sLine = sLine.."   "..SKM_Config.Col_Label.."( ";
	--sLine = sLine..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Full..SKM_Config.Col_PlayerFullKill..iFullKill;
	--sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Standard..SKM_Config.Col_PlayerKill..iKill; -- 0.08.2 Add localization
	--sLine = sLine..SKM_Config.Col_Label.." + "..SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.List_Frame_Assist..SKM_Config.Col_PlayerAssistKill..iAssistKill..SKM_Config.Col_Label.." )"; -- 0.08.2 Add localization

	local sKillDetail = SKM_Config.Col_LabelTitle..SKM_UI_STRINGS.Small_Target_Honor..SKM_Config.Col_HonorKill..iHonorKill.."  ";
	if (iRemaining == 0) then
		sKillDetail = sKillDetail..SKM_Config.Col_Label.."( "..SKM_Config.Col_Honorless..SKM_UI_STRINGS.Small_Target_NoHonor..SKM_Config.Col_Label.." )";
	else
		sKillDetail = sKillDetail..SKM_Config.Col_Label.."( "..SKM_Config.Col_HonorKill..iRemaining..SKM_Config.Col_Label.." )";
	end
	sLine	= sLine.."     "..sKillDetail;

	table.insert(Lines, sLine);


	if (Enemy[_SKM._atWar] == true) then
		local sLine = "";
		sLine = sLine..SKM_Config.Col_PlayerWar.. SKM_UI_STRINGS.Small_Target_War;
		if (Enemy[_SKM._warDate]) then
				local sDisplayDate = string.sub(Enemy[_SKM._warDate], 1, 10);
				sLine = sLine..SKM_Config.Col_PlayerWar .. SKM_UI_STRINGS.Since .. sDisplayDate;
		end


		table.insert(Lines, sLine);
	end

	SKMap_TooltipAddLines(Lines);
end


function SKMap_TooltipEnemyNote(sName)
	local FName = "SKMap_TooltipEnemyNote";

	local Enemy = SKM_Data[_RealmName][_PlayerName].EnemyHistory[sName];
	if (not Enemy) then
		SkM_Trace(FName, 2, "Unknown enemy : "..snil(sName));
		return false;
	end


	local Lines = { };
	if (Enemy[_SKM._playerNote] ~= nil) and (Enemy[_SKM._playerNote] ~= "") then
		local sLine = Enemy[_SKM._playerNote];
		SkM_TableInsertMaxLengthLine(Lines, sLine, SKM_Config.MaxFormatLineLength, SKM_Config.FormatLineThreshold, SKM_Config.Col_Label);
	end

	SKMap_TooltipAddLines(Lines);
end


function SKMap_OptionsFrame_ScrollUpdate()
	SKMap_OptionsFrame_Load();
end


function SKMap_GetOptionLine(elemID)
	local lineID = elemID;
	if (not SKM_List_Options) then
		return nil;
	end

	if (lineID > 100) then
		lineID = lineID - 100;

		if (SKM_List_Options[lineID]) and (SKM_List_Options[lineID].Right) then

			return SKM_List_Options[lineID].Right;

		end
	else
		if (SKM_List_Options[lineID]) and (SKM_List_Options[lineID].Left) then
			return SKM_List_Options[lineID].Left;
		end
	end
	return nil;
end

function SKMap_OptionChecked()
	local FName = "SKMap_OptionChecked";
	--local id = this:GetID();
	local id = this:GetParent():GetID();
	SkM_Trace(FName, 3, "id = "..snil(id));

	local sOption = SKMap_GetOptionLine(id);
	SkM_Trace(FName, 2, "Option = "..snil(sOption));

	local OptionName = this:GetName();
	local MyButton = getglobal(OptionName);

	if (not MyButton:GetChecked()) then
		SkM_SetOption(sOption, false);
	else
		SkM_SetOption(sOption, true);
	end

	if (sOption == "ShowMinimapButton") then
		SKMap_SetMiniMapIcon();
	end
end

function SKMap_OptionSliderChange()
	local FName = "SKMap_OptionSliderChange";
	--local id = this:GetID();
	local id = this:GetParent():GetID();
	local sOption = SKMap_GetOptionLine(id);

	local SliderName = this:GetName();
	SkM_Trace(FName, 4, "Slider name = "..SliderName);

	local MySlider = getglobal(SliderName);
	local SliderText = getglobal(SliderName.."Text");

	iValue = MySlider:GetValue();
	SliderText:SetText(iValue);

	SkM_SetOption(sOption, iValue);

	if (sOption == "MinimapButtonPosition") or (sOption == "MinimapButtonOffset") then
		SKMap_SetMiniMapIcon();
	end

end


function SKMap_IconButtonClicked()
	--local id = this:GetID();
	local id = this:GetParent():GetID();
	local iCateg = SKM_List_Options[id].Category;
	if (iCateg) then
		if (SKM_OptionsList[iCateg].Expanded == true) then
			SKM_OptionsList[iCateg].Expanded = false
		else
			SKM_OptionsList[iCateg].Expanded = true;
		end
		SKMap_OptionsFrame_Load();
	end
end


function SKMap_OptionExpandAll()
	local i;
	for i=1,table.getn(SKM_OptionsList),1 do
		SKM_OptionsList[i].Expanded = true;
	end
	SKMap_OptionsFrame_Load();
end

function SKMap_OptionCollapseAll()
	local i;
	for i=1,table.getn(SKM_OptionsList),1 do
		SKM_OptionsList[i].Expanded = false;
	end
	SKMap_OptionsFrame_Load();
end



function SKMap_EnemyList_ResetSort()

	if (SKM_List_ActiveList == _SKM._players) then
		SKM_Settings.EnemyList_SortType = SKM_Config.EnemyList_SortType;
		SKM_Settings.EnemyList_SortTypes = SKM_Config.EnemyList_SortTypes;
		SKM_Settings.EnemyList_ReverseSort = SKM_Config.EnemyList_ReverseSort;

		SKMap_ListFrame_SortList();
	elseif (SKM_List_ActiveList == _SKM._guilds) then
		SKM_Settings.GuildList_SortType = SKM_Config.GuildList_SortType;
		SKM_Settings.GuildList_SortTypes = SKM_Config.GuildList_SortTypes;
		SKM_Settings.GuildList_ReverseSort = SKM_Config.GuildList_ReverseSort;

		SKMap_ListFrame_SortGuildList();
	end
end

function SKMap_DuelList_ResetSort()
	SKM_Settings.DuelList_SortType = SKM_Config.DuelList_SortType;
	SKM_Settings.DuelList_SortTypes = SKM_Config.DuelList_SortTypes;
	SKM_Settings.DuelList_ReverseSort = SKM_Config.DuelList_ReverseSort;

	SKMap_DuelFrame_SortList();
end




-- check if the enemy players list displayed in the GUI has to be generated
-- or if it is not required.
function SKMap_PlayerListUpdateNeeded()
	local bUpdate = false;
	local curTime = GetTime();

	if (SKM_Context.LastPlayerListUpdate == nil) then
		bUpdate = true;
	else
		if (SKM_Context.PlayerDataChanged) then
			if (SkM_GetOption("EnemyListAutoUpdate"))
			and ((curTime - SKM_Context.LastPlayerListUpdate) > SkM_GetOption("EnemyListAutoUpdateDelay")) then
				bUpdate = true;
			end
		end
	end

	if (bUpdate) then
		SKM_Context.LastPlayerListUpdate = curTime;
		SKM_Context.PlayerDataChanged = false;
	end
	return bUpdate;
end


function SKMap_ListFrame_UpdateListButtonClick()
	local curTime = GetTime();

	if (SKM_List_ActiveList == _SKM._players) then

		SKM_Context.LastPlayerListUpdate = curTime;
		SKM_Context.PlayerDataChanged = false;

		SKMap_SetListContent();
		SKMap_ListFrame_UpdateList();
		SKMap_ListFrame_SortList();
	end
end

