Quantcast

121017

Jennifer [09-09-19 - 17:10]
121017
Filename
CHANGELOG.txt
Core/Communications-Classic.lua
Core/Core-Classic.lua
Core/Message-Classic.lua
Core/Module-Classic.lua
Core/Tag-Classic.lua
Core/Team-Classic.lua
EMA-Classic.toc
EbonyUtilities.lua
Modules/ItemUse-Classic.lua
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 60bb904..96cc170 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -2,12 +2,12 @@
 ChangeLogs:
 ---------------------------

-EMA Version: v1.13.2-Release-v0.4(121016)
+EMA Version: v1.13.2-Release-v0.4(121016/121017)
 Game Version: 1.13.2
-Release Date: 08/9/2019
+Release Date: 09/9/2019

 #Item_Bar
-	- Fixed a Lag bug i hope when you have quest items added to bar
+	- Fixed a Lag bug i hope when you have quest items added to bar, added 121017 Now fixed the UI from crashing!



diff --git a/Core/Communications-Classic.lua b/Core/Communications-Classic.lua
new file mode 100644
index 0000000..d271993
--- /dev/null
+++ b/Core/Communications-Classic.lua
@@ -0,0 +1,671 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+local EMA = LibStub( "AceAddon-3.0" ):NewAddon(
+	"Communications",
+	"AceComm-3.0",
+	"AceEvent-3.0",
+	"AceConsole-3.0",
+	"AceTimer-3.0",
+	"AceHook-3.0"
+)
+
+-- Get the locale for EMACommunications.
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+
+-- Get libraries.
+local EMAUtilities = LibStub:GetLibrary( "EbonyUtilities-1.0" )
+local AceSerializer = LibStub:GetLibrary( "AceSerializer-3.0" )
+
+local EMAHelperSettings = LibStub:GetLibrary( "EMAHelperSettings-1.0" )
+
+-- EMACommunications is not a module, but the same naming convention for these values is convenient.
+EMA.moduleName = "Communications"
+EMA.moduleDisplayName = L["COMMUNICATIONS"]
+EMA.settingsDatabaseName = "CommunicationsProfileDB"
+EMA.parentDisplayName = L["OPTIONS"]
+EMA.chatCommand = "ema-comm"
+EMA.teamModuleName = "Team"
+-- Icon
+EMA.moduleIcon = "Interface\\Addons\\EMA-Classic\\Media\\CommsLogo.tga"
+-- order
+EMA.moduleOrder = 20
+
+-------------------------------------------------------------------------------------------------------------
+-- Constants
+-------------------------------------------------------------------------------------------------------------
+
+-- Communication methods.
+EMA.COMMUNICATION_WHISPER = "WHISPER"
+EMA.COMMUNICATION_GROUP = "RAID"
+EMA.COMMUNICATION_GUILD = "GUILD"
+
+-- Communication message prefix.
+EMA.MESSAGE_PREFIX = "JmbCmMsg"
+
+
+-- Communication priorities.
+EMA.COMMUNICATION_PRIORITY_BULK = "BULK"
+EMA.COMMUNICATION_PRIORITY_NORMAL = "NORMAL"
+EMA.COMMUNICATION_PRIORITY_ALERT = "ALERT"
+
+-- Communication command.
+EMA.COMMAND_PREFIX = "JmbCmCmd"
+EMA.COMMAND_SEPERATOR = "\004"
+EMA.COMMAND_ARGUMENT_SEPERATOR = "\005"
+
+-- Internal commands sent by EMA Communications.
+EMA.COMMAND_INTERNAL_SEND_SETTINGS = "JmbCmSdSet"
+
+-------------------------------------------------------------------------------------------------------------
+-- Messages module sends.
+-------------------------------------------------------------------------------------------------------------
+
+
+-- Get a settings value.
+function EMA:ConfigurationGetSetting( key )
+	return EMA.db[key[#key]]
+end
+
+-- Set a settings value.
+function EMA:ConfigurationSetSetting( key, value )
+	EMA.db[key[#key]] = value
+end
+
+-- Settings - the values to store and their defaults for the settings database.
+EMA.settings = {
+	profile = {
+		autoSetTeamOnlineorOffline = true,
+		boostCommunication = true,
+		useGuildComms = false,
+	},
+}
+
+-- Configuration.
+local function GetConfiguration()
+	local configuration = {
+		name = EMA.moduleDisplayName,
+		handler = EMA,
+		type = 'group',
+		get = "ConfigurationGetSetting",
+		set = "ConfigurationSetSetting",
+		args = {
+			type = "input",
+				name = L["OPEN_CONFIG"],
+				desc = L["OPEN_CONFIG_HELP"],
+				usage = "/ema-comm config",
+				get = false,
+				set = "",
+				guiHidden = true,
+			push = {
+				type = "input",
+				name = L["PUSH_SETTINGS"],
+				desc = L["PUSH_SETTINGS_INFO"],
+				usage = "/ema-comm push",
+				get = false,
+				set = "EMASendSettings",
+			},
+		},
+	}
+	return configuration
+end
+
+
+-- Debug message.
+function EMA:DebugMessage( ... )
+    --EMA:Print( ... )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Character online management.
+-------------------------------------------------------------------------------------------------------------
+local function IsCharacterOnline( characterName )
+	return EMAPrivate.Team.GetCharacterOnlineStatus( characterName )
+end
+
+local function AssumeTeamAlwaysOnline()
+	return "false"
+end
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Command management.
+-------------------------------------------------------------------------------------------------------------
+
+-- Creates a command to send.
+local function CreateCommandToSend( moduleName, commandName, ... )
+	--EMA:Print("Create", moduleName, commandName)
+	-- Start the message with the module name and a seperator.
+	local message = moduleName..EMA.COMMAND_SEPERATOR
+	-- Add the command  name and a seperator.
+	message = message..commandName..EMA.COMMAND_SEPERATOR
+	-- Add any arguments to the message (serialized and seperated).
+	local numberArguments = select( "#", ... )
+
+	for iterateArguments = 1, numberArguments do
+		local argument = select( iterateArguments, ... )
+		message = message..AceSerializer:Serialize( argument )
+		if iterateArguments < numberArguments then
+			message = message..EMA.COMMAND_ARGUMENT_SEPERATOR
+		end
+	end
+	-- Return the command to send.
+	--EMA:Print("Create", moduleName, commandName, iterateArguments)
+	return message
+end
+
+
+local function CommandAll( moduleName, commandName, ... )
+   -- EMA:DebugMessage( "Command All: ", moduleName, commandName, ... )
+	--EMA:Print( "Command All: ", moduleName, commandName, ... )
+	-- Get the message to send.
+	local message = CreateCommandToSend( moduleName, commandName, ... )
+	local channel
+	if EMA.db.useGuildComms == true then
+			EMA:SendCommMessage(
+			EMA.COMMAND_PREFIX,
+			message,
+			EMA.COMMUNICATION_GUILD,
+			nil,
+			EMA.COMMUNICATION_PRIORITY_ALERT
+			)
+		return
+	end
+	-- toon has to be in a group
+	if UnitInBattleground( "player" ) then
+		EMA:DebugMessage( "PvP_INSTANCE")
+		channel = "INSTANCE_CHAT"
+	elseif IsInGroup() then
+		EMA:DebugMessage( "Group")
+		local isInstance, instanceType = IsInInstance()
+		local name, Type, difficulty, difficultyName, maxPlayers, playerDifficulty, isDynamicInstance = GetInstanceInfo()
+		if isInstance or instanceType == "raid" or IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
+			if IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
+				channel = "INSTANCE_CHAT"
+			else
+				if IsInRaid() then
+					channel = "RAID"
+				else
+					channel = "PARTY"
+				end
+			end
+		else
+			if IsInRaid() then
+				channel = "RAID"
+			else
+				channel = "PARTY"
+			end
+		end
+	end
+	--EMA:Print( "CHANNEL", channel)
+	if channel then
+	EMA:DebugMessage("Sending command to group.", message, "channel", channel, nil)
+		--EMA:Print("Sending command to group.", message, "channel", channel, nil)
+			--EMA.COMMUNICATION_GROUP,
+			EMA:SendCommMessage(
+			EMA.COMMAND_PREFIX,
+			message,
+			channel,
+			nil,
+			EMA.COMMUNICATION_PRIORITY_ALERT
+			)
+			--EMA:Print("testChennel", EMA.COMMAND_PREFIX, channel, EMA.COMMUNICATION_PRIORITY_ALERT)
+			--return
+	end
+	--if the unit is not in the party then it unlikely did not get the party message,
+	for characterName, characterOrder in EMAPrivate.Team.TeamList() do
+		if UnitInParty( Ambiguate( characterName, "none" ) ) == false then
+			EMA:DebugMessage( "Toon not in party:", characterName)
+			if IsCharacterOnline( characterName ) == true then
+				EMA:DebugMessage("Sending command to others not in party/raid.", message, "WHISPER", characterName)
+				EMA:SendCommMessage(
+				EMA.COMMAND_PREFIX,
+				message,
+				EMA.COMMUNICATION_WHISPER,
+				characterName,
+				EMA.COMMUNICATION_PRIORITY_ALERT
+				)
+				--EMA:Print("testWis", EMA.COMMAND_PREFIX, EMA.COMMUNICATION_WHISPER, characterName , EMA.COMMUNICATION_PRIORITY_ALERT)
+			end
+		end
+	end
+end
+
+
+
+-- Should this get removed at some point and use all comms on one channel???
+-- WHISPER's don't work cross-realm but do work connected-realm so sending msg to masters would not send.
+-- TODO: Maybe remove masters???, and fall back to everyone being the master?
+-- Not really sure what to do so for now will keep with the master, and whisper them,
+-- if was to use party/raid then everyone will get the command and masters would not work.
+
+-- Send a command to the master.
+local function CommandMaster( moduleName, commandName, ... )
+    EMA:DebugMessage( "Command Master: ", moduleName, commandName, ... )
+	-- Get the message to send.
+	local message = CreateCommandToSend( moduleName, commandName, ... )
+	-- Send the message to the master.
+	local characterName = EMAPrivate.Team.GetMasterName()
+		if IsCharacterOnline( characterName ) == true then
+			EMA:DebugMessage("Sending command to others not in party/raid.", message, "WHISPER", characterName)
+				EMA:SendCommMessage(
+				EMA.COMMAND_PREFIX,
+				message,
+				EMA.COMMUNICATION_WHISPER,
+				characterName,
+				EMA.COMMUNICATION_PRIORITY_ALERT
+				)
+		end
+end
+
+-- Send a command to the master.
+local function CommandToon( moduleName, characterName, commandName, ... )
+	-- Get the message to send.
+	local message = CreateCommandToSend( moduleName, commandName, ... )
+		if IsCharacterOnline( characterName ) == true then
+			EMA:DebugMessage("Sending command to others not in party/raid.", message, "WHISPER", characterName)
+				EMA:SendCommMessage(
+				EMA.COMMAND_PREFIX,
+				message,
+				EMA.COMMUNICATION_WHISPER,
+				characterName,
+				EMA.COMMUNICATION_PRIORITY_ALERT
+				)
+		end
+end
+
+-- EbonyTest
+-- hide offline player spam Not really the best way but it works, Maybe adding tick box's to set members offline? This should now work with elvUI?
+
+local function SystemSpamFilter(frame, event, message)
+	if( event == "CHAT_MSG_SYSTEM") then
+		if message:match(string.format(ERR_CHAT_PLAYER_NOT_FOUND_S, "(.+)")) then
+			local SearchPlayerNotFound = gsub(ERR_CHAT_PLAYER_NOT_FOUND_S, "%%s", "(.+)")  -- Get from "No player named '%s' is currently playing."
+			local _, _, characterName = strfind(message, SearchPlayerNotFound)
+			if EMAApi.IsCharacterInTeam(characterName) == true then
+				--EMA:Print("player offline in team", characterName )
+				if EMA.db.autoSetTeamOnlineorOffline == true then
+					if IsCharacterOnline( characterName ) == true then
+						EMAApi.setOffline( characterName, false )
+						--EMA:Print("player offline in team", characterName )
+					end
+				end
+				return true
+			else
+				--EMA:Print("player offline Not in team")
+				return
+			end
+		end
+		if message:match(string.format(ERR_NOT_IN_RAID, "(.+)")) then
+			return true
+		end
+	end
+    return false
+end
+ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", SystemSpamFilter)
+
+
+
+-- Receive a command from another character.
+function EMA:CommandReceived( prefix, message, distribution, sender )
+    local characterName = EMAUtilities:AddRealmToNameIfMissing( sender )
+	EMA:DebugMessage( "Command received: ", prefix, message, distribution, sender )
+	--EMA:Print( "Command received: ", prefix, message, distribution, sender )
+	-- Check if the command is for EMA Communications.
+	if prefix == EMA.COMMAND_PREFIX then
+		--checks the char is in the team if not everyone can change settings and we do not want that
+		if EMAPrivate.Team.IsCharacterInTeam( sender ) == true then
+		    EMA:DebugMessage( "Sender is in team list." )
+		   --automaic setting team members online.
+			--EMA:Print("toonnonline", sender )
+				if EMAPrivate.Team.GetCharacterOnlineStatus( characterName ) == false then
+					--EMA:Print("Setting Toon online", distribution, sender, characterName )
+					EMAApi.setOnline( characterName, true)
+				end
+			-- Split the command into its components.
+			local moduleName, commandName, argumentsStringSerialized = strsplit( EMA.COMMAND_SEPERATOR, message )
+			local argumentsTable  = {}
+			-- Are there any arguments?
+			if (argumentsStringSerialized ~= nil) and (argumentsStringSerialized:trim() == "") then
+				-- No.
+				else
+					-- Deserialize the arguments.
+					local argumentsTableSerialized = { strsplit( EMA.COMMAND_ARGUMENT_SEPERATOR, argumentsStringSerialized ) }
+					for index, argumentSerialized in ipairs( argumentsTableSerialized ) do
+						local success, argument = AceSerializer:Deserialize( argumentSerialized )
+						if success == true then
+							table.insert( argumentsTable, argument )
+						else
+							error( L["A: Failed to deserialize command arguments for B from C."]( "EMA", moduleName, sender ) )
+						end
+					end
+				end
+				-- Look for internal EMA Communication commands.
+				if commandName == EMA.COMMAND_INTERNAL_SEND_SETTINGS then
+					-- Tell EMACore to handle the settings received.
+					EMAPrivate.Core.OnSettingsReceived( sender, moduleName, unpack( argumentsTable ) )
+				else
+					-- Any other command can go directly to the module that sent it.
+					EMA:DebugMessage( "Sending command on to module: ", sender, moduleName, commandName, unpack( argumentsTable ) )
+					EMAPrivate.Core.OnCommandReceived( sender, moduleName, commandName, unpack( argumentsTable ) )
+				end
+			else
+				EMA:DebugMessage( "Sender is NOT in team list." )
+			end
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Communications API.  These methods should only be called by EMA Core.
+-------------------------------------------------------------------------------------------------------------
+
+-- Send settings to all members of the current team.
+local function SendSettings( moduleName, settings )
+	-- Send a push settings command to all.
+	--EMA:Print("test", moduleName, EMA.COMMAND_INTERNAL_SEND_SETTINGS, settings )
+	CommandAll( moduleName, EMA.COMMAND_INTERNAL_SEND_SETTINGS, settings )
+end
+
+-- Command all members of the current team.
+local function SendCommandAll( moduleName, commandName, ... )
+	-- Send the command to all.
+	CommandAll( moduleName, commandName, ... )
+end
+
+-- TODO: needs to be cleaned up at some point with other communication stuff
+
+-- Command the master.
+local function SendCommandMaster( moduleName, commandName, ... )
+	-- Send the command to the master character.
+	CommandMaster( moduleName, commandName, ... )
+end
+
+-- Command the master.
+local function SendCommandToon( moduleName, characterName, commandName, ... )
+	-- Send the command to the master character.
+	CommandToon( moduleName, characterName, commandName, ... )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Communications Initialization.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialize the addon.
+function EMA:OnInitialize()
+	--EMA.channelPollTimer = nil
+	-- Register commands with AceComms - tell AceComms to call the CommandReceived function when a command is received.
+	EMA:RegisterComm( EMA.COMMAND_PREFIX, "CommandReceived" )
+	-- Create the settings database supplying the settings values along with defaults.
+    EMA.completeDatabase = LibStub( "AceDB-3.0" ):New( EMA.settingsDatabaseName, EMA.settings )
+	EMA.db = EMA.completeDatabase.profile
+	-- Create the settings.
+	LibStub( "AceConfig-3.0" ):RegisterOptionsTable(
+		EMA.moduleName,
+		GetConfiguration()
+	)
+	EMA:SettingsCreate()
+	EMA.settingsFrame = EMA.settingsControl.widgetSettings.frame
+	EMA:SettingsRefresh()
+	--TODO: Is this needed? as its already in a module??
+	local k = GetRealmName()
+	local realm = k:gsub( "%s+", "" )
+	self.characterRealm = realm
+	self.characterNameLessRealm = UnitName( "player" )
+	self.characterName = self.characterNameLessRealm.."-"..self.characterRealm
+	EMA.characterGUID = UnitGUID( "player" )
+	-- End of needed:
+	-- Register communications as a module.
+	EMAPrivate.Core.RegisterModule( EMA, EMA.moduleName )
+end
+
+function EMA:OnEnable()
+
+	EMA:RegisterEvent("GUILD_ROSTER_UPDATE")
+	if EMA.db.boostCommunication == true then
+		EMA:BoostCommunication()
+		-- Repeat every 5 minutes.
+		EMA:ScheduleRepeatingTimer( "BoostCommunication", 300 )
+	end
+end
+
+function EMA:BoostCommunication()
+	if EMA.db.boostCommunication == true then
+		-- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
+		ChatThrottleLib.MAX_CPS = 1200 --800
+		-- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
+		ChatThrottleLib.MSG_OVERHEAD = 40
+		-- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
+		ChatThrottleLib.BURST = 6000 --4000
+		-- Reduce output CPS to half (and don't burst) if FPS drops below this value
+		ChatThrottleLib.MIN_FPS = 10 --20
+	end
+end
+
+-- Handle the chat command.
+function EMA:EMAChatCommand( input )
+    if not input or input:trim() == "" then
+        InterfaceOptionsFrame_OpenToCategory( EMA.moduleDisplayName )
+    else
+        LibStub( "AceConfigCmd-3.0" ):HandleCommand( EMA.chatCommand, EMA.moduleName, input )
+    end
+end
+
+function EMA:OnDisable()
+end
+
+function EMA:GUILD_ROSTER_UPDATE(event, ... )
+	if EMA.db.useGuildComms == false then
+		return
+	end
+	local numGuildMembers, numOnline, numOnlineAndMobile = GetNumGuildMembers()
+	for index = 1, numGuildMembers do
+		characterName,_,_,_,class,_,_,_,online,status,classFileName,_, _,isMobile = GetGuildRosterInfo(index)
+		--EMA:Print("Name", fullName, "online", online )
+		if online == false then
+			if EMA.db.autoSetTeamOnlineorOffline == true then
+				if EMAApi.IsCharacterInTeam(characterName) == true and IsCharacterOnline( characterName ) == true then
+					EMAApi.setOffline( characterName, false )
+					--EMA:Print("player offline in team", characterName )
+				end
+			end
+		end
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:SettingsCreate()
+	EMA.settingsControl = {}
+	EMAHelperSettings:CreateSettings(
+		EMA.settingsControl,
+		EMA.moduleDisplayName,
+		EMA.parentDisplayName,
+		EMA.EMASendSettings,
+		EMA.moduleIcon,
+		EMA.moduleOrder
+
+	)
+	local bottomOfOptions = EMA:SettingsCreateOptions( EMAHelperSettings:TopOfSettings() )
+	EMA.settingsControl.widgetSettings.content:SetHeight( -bottomOfOptions )
+	-- Help
+	local helpTable = {}
+	EMAHelperSettings:CreateHelp( EMA.settingsControl, helpTable, GetConfiguration() )
+end
+
+function EMA:SettingsCreateOptions( top )
+	-- Get positions and dimensions.
+	local checkBoxHeight = EMAHelperSettings:GetCheckBoxHeight()
+	local labelContinueHeight = EMAHelperSettings:GetContinueLabelHeight()
+	local editBoxHeight = EMAHelperSettings:GetEditBoxHeight()
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local halfWidth = (headingWidth - horizontalSpacing) / 2
+	local column1Left = left
+	local column2Left = left + 10
+	local movingTop = top
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["COMMUNICATIONS"]..L[" "]..L["OPTIONS"] , movingTop, false )--
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.checkBoxAutoSetTeamOnlineorOffline = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		movingTop,
+		L["AUTO_SET_TEAM"],
+		EMA.CheckBoxAutoSetTeamOnlineorOffline
+	)
+	movingTop = movingTop - checkBoxHeight
+	EMA.settingsControl.checkBoxBoostCommunication = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		movingTop,
+		L["BOOST_COMMUNICATIONS"],
+		EMA.CheckBoxBoostCommunication,
+		L["BOOST_COMMUNICATIONS_HELP"]
+	)
+	movingTop = movingTop - checkBoxHeight
+	EMA.settingsControl.checkBoxUseGuildComms = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		movingTop,
+		L["USE_GUILD_COMMS"],
+		EMA.CheckBoxUseGuildComms,
+		L["USE_GUILD_COMMS_INFO"]
+	)
+	movingTop = movingTop - checkBoxHeight
+	return movingTop
+end
+
+function EMA:CheckBoxUseGuildComms( event, value )
+	EMA.db.useGuildComms = value
+	EMA:SettingsRefresh()
+end
+
+function EMA:CheckBoxBoostCommunication( event, value )
+	EMA.db.boostCommunication = value
+	EMA:SettingsRefresh()
+end
+
+function EMA:CheckBoxAssumeAlwaysOnline( event, value )
+	EMA.db.assumeTeamAlwaysOnline = value
+	EMA:SettingsRefresh()
+end
+
+function EMA:CheckBoxAutoSetTeamOnlineorOffline( event, value )
+	EMA.db.autoSetTeamOnlineorOffline = value
+	EMA:SettingsRefresh()
+end
+
+function EMA:BeforeEMAProfileChanged()
+end
+
+function EMA:OnEMAProfileChanged()
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsRefresh()
+	EMA.settingsControl.checkBoxAutoSetTeamOnlineorOffline:SetValue( EMA.db.autoSetTeamOnlineorOffline )
+	EMA.settingsControl.checkBoxBoostCommunication:SetValue( EMA.db.boostCommunication )
+	EMA.settingsControl.checkBoxUseGuildComms:SetValue( EMA.db.useGuildComms )
+end
+
+-- Settings received.
+function EMA:EMASendSettings()
+	SendSettings( EMA.moduleName, EMA.db )
+end
+
+-- Settings received.
+function EMA:EMAOnSettingsReceived( characterName, settings )
+	if characterName ~= EMA.characterName then
+		-- Update the settings.
+		EMA.db.autoSetTeamOnlineorOffline = settings.autoSetTeamOnlineorOffline
+		EMA.db.boostCommunication = settings.boostCommunication
+		EMA.db.useGuildComms = settings.useGuildComms
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		-- Tell the player.
+		EMA:Print( L["SETTINGS_RECEIVED_FROM_A"]( characterName ) )
+	end
+end
+
+-- text = message to send -- This is mosty used for sending over EMA Own Comms mosty of Whispers
+-- chatDestination = "PARTY, WHISPER, RAID, CHANNEL, etc"
+-- characterOrChannelName = character name if WHISPER or channel name if CHANNEL or nil otherwise
+-- If we clean up EMA-msg then we can remove this maybe again Eboyn TODO::::
+-- priority = one of
+--   EMA.COMMUNICATION_PRIORITY_BULK,
+--   EMA.COMMUNICATION_PRIORITY_NORMAL
+--   EMA.COMMUNICATION_PRIORITY_ALERT
+
+local function SendChatMessage( text, chatDestination, characterOrChannelName, priority )
+	-- Message small enough to send?
+	--EMA:Print("test", text, chatDestination, characterOrChannelName, priority)
+	if text:len() <= 255 then
+		--EMA:Print("test TURE!!!!! TOBIG" )
+		ChatThrottleLib:SendChatMessage( priority, EMA.MESSAGE_PREFIX, text, chatDestination, nil, characterOrChannelName, nil )
+
+
+	else
+		-- No, message is too big, split into smaller messages, taking UTF8 characters into account.
+		local bytesAvailable = string.utf8len(text1)
+		local currentPosition = 1
+		local countBytes = 1
+		local startPosition = currentPosition
+		local splitText = ""
+		-- Iterate all the utf8 characters, character by character until we reach 255 characters, then send
+		-- those off and start counting over.
+		while currentPosition <= bytesAvailable do
+			-- Count the number of bytes the character at this position takes up.
+			countBytes = countBytes + EMAutf8charbytes( text, currentPosition )
+			-- More than 255 bytes yet?
+			if countBytes <= 255 then
+				-- No, increment the position and keep counting.
+				currentPosition = currentPosition + EMAutf8charbytes( text, currentPosition )
+			else
+				-- Yes, more than 255.  Send this amount off.
+				splitText = text:sub( startPosition, currentPosition )
+				ChatThrottleLib:SendChatMessage( priority, EMA.MESSAGE_PREFIX, splitText, chatDestination, nil, characterOrChannelName, nil )
+				-- New start position and count.
+				startPosition = currentPosition + 1
+				countBytes = 1
+			end
+		end
+		-- Any more bytes left to send?
+		if startPosition < currentPosition then
+			-- Yes, send them.
+			splitText = text:sub( startPosition, currentPosition )
+			ChatThrottleLib:SendChatMessage( priority, EMA.MESSAGE_PREFIX, splitText, chatDestination, nil, characterOrChannelName, nil )
+		end
+	end
+end
+
+EMAPrivate.Communications.COMMUNICATION_PRIORITY_BULK = EMA.COMMUNICATION_PRIORITY_BULK
+EMAPrivate.Communications.COMMUNICATION_PRIORITY_NORMAL = EMA.COMMUNICATION_PRIORITY_NORMAL
+EMAPrivate.Communications.COMMUNICATION_PRIORITY_ALERT = EMA.COMMUNICATION_PRIORITY_ALERT
+EMAPrivate.Communications.SendChatMessage = SendChatMessage
+EMAPrivate.Communications.SendSettings = SendSettings
+EMAPrivate.Communications.SendCommandAll = SendCommandAll
+EMAPrivate.Communications.SendCommandMaster = SendCommandMaster
+EMAPrivate.Communications.SendCommandToon = SendCommandToon
+EMAPrivate.Communications.SendCommandMaster = SendCommandMaster
+EMAPrivate.Communications.SendCommandToon = SendCommandToon
+EMAPrivate.Communications.AssumeTeamAlwaysOnline = AssumeTeamAlwaysOnline
\ No newline at end of file
diff --git a/Core/Core-Classic.lua b/Core/Core-Classic.lua
new file mode 100644
index 0000000..742a746
--- /dev/null
+++ b/Core/Core-Classic.lua
@@ -0,0 +1,969 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+-- The global private table for EMA.
+EMAPrivate = {}
+EMAPrivate.Core = {}
+EMAPrivate.Communications = {}
+EMAPrivate.Message = {}
+EMAPrivate.Team = {}
+EMAPrivate.Tag = {}
+
+-- The global public API table for EMA.
+_G.EMAApi = {}
+
+local EMA = LibStub( "AceAddon-3.0" ):NewAddon(
+	"EMACore",
+	"AceConsole-3.0"
+)
+
+-- EMACore is not a module, but the same naming convention for these values is convenient.
+EMA.moduleName = "EMA-Core"
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+EMA.moduleDisplayName = L["NEWS"]
+EMA.settingsDatabaseName = "CoreProfileDB"
+EMA.parentDisplayName = L["NEWS"]
+EMA.chatCommand = "ema"
+EMA.teamModuleName = "Team"
+-- Icon's
+EMA.moduleIcon = "Interface\\Addons\\EMA-Classic\\Media\\NewsIcon.tga"
+EMA.pofileIcon = "Interface\\Addons\\EMA-Classic\\Media\\SettingsIcon.tga"
+-- order
+EMA.moduleOrder = 1
+
+
+-- Load libraries.
+local AceGUI = LibStub("AceGUI-3.0")
+local EMAUtilities = LibStub:GetLibrary( "EbonyUtilities-1.0" )
+local EMAHelperSettings = LibStub:GetLibrary( "EMAHelperSettings-1.0" )
+
+
+-- Create frame for EMA Settings.
+EMAPrivate.SettingsFrame = {}
+EMAPrivate.SettingsFrame.Widget = AceGUI:Create( "EMAWindow" )
+EMAPrivate.SettingsFrame.Widget:SetTitle( "" )
+EMAPrivate.SettingsFrame.Widget:SetStatusText(L["STATUSTEXT"])
+EMAPrivate.SettingsFrame.Widget:SetWidth(900)
+EMAPrivate.SettingsFrame.Widget:SetHeight(800)
+EMAPrivate.SettingsFrame.Widget:SetLayout( "Fill" )
+EMAPrivate.SettingsFrame.WidgetTree = AceGUI:Create( "EMATreeGroup" )
+EMAPrivate.SettingsFrame.WidgetTree:SetLayout( "Fill" )
+EMAPrivate.SettingsFrame.TreeGroupStatus = { treesizable = false, groups = {} }
+EMAPrivate.SettingsFrame.WidgetTree:SetStatusTable( EMAPrivate.SettingsFrame.TreeGroupStatus )
+EMAPrivate.SettingsFrame.WidgetTree:EnableButtonTooltips( false )
+EMAPrivate.SettingsFrame.Widget:AddChild( EMAPrivate.SettingsFrame.WidgetTree )
+
+
+function EMA:OnEnable()
+	local Jamba = IsAddOnLoaded("Jamba")
+	if Jamba == true then
+		StaticPopup_Show( "CAN_NOT_RUN_JAMBA_AND_EMA" )
+	end
+	--[[
+	if EMA.db.global.showStartupMessage8000 then
+		StaticPopup_Show( "ALL_SETTINGS HAVE BEEN RESET" )
+	end
+	]]
+	if EMA.db.global.showStartupMessage2000 then
+		StaticPopup_Show( "UpgradeTo_v2" )
+	end
+	if EMA.db.global.showStartupMessageClassic then
+		StaticPopup_Show( "Welcome_To_Classic" )
+	end
+end
+
+function EMA:OnDisable()
+end
+
+local function InitializePopupDialogs()
+	StaticPopupDialogs["ALL_SETTINGS HAVE BEEN RESET"] = {
+		text = L["ALL_SETTINGS_RESET"],
+		button1 = OKAY,
+		OnAccept = function()
+			EMA.db.global.showStartupMessage8000 = false
+		end,
+		showAlert = 1,
+		timeout = 0,
+		exclusive = 1,
+		hideOnEscape = 1,
+		whileDead = 1,
+	}
+	StaticPopupDialogs["CAN_NOT_RUN_JAMBA_AND_EMA"] = {
+		text = L["CAN_NOT_RUN_JAMBA_AND_EMA"],
+		button1 = OKAY,
+		OnAccept = function()
+			DisableAddOn("jamba")
+			ReloadUI()
+		end,
+		showAlert = 1,
+		timeout = 0,
+		exclusive = 1,
+		hideOnEscape = 0,
+		whileDead = 1,
+	}
+	StaticPopupDialogs["UpgradeTo_v2"] = {
+		text = L["v2_NEWS"],
+		button1 = OKAY,
+		OnAccept = function()
+			EMA.db.global.showStartupMessage2000 = false
+		end,
+		showAlert = 1,
+		timeout = 0,
+		exclusive = 1,
+		hideOnEscape = 0,
+		whileDead = 1,
+	}
+	StaticPopupDialogs["Welcome_To_Classic"] = {
+		text = L["CLASSIC_NEWS"],
+		button1 = OKAY,
+		OnAccept = function()
+			EMA.db.global.showStartupMessageClassic = false
+		end,
+		showAlert = 1,
+		timeout = 0,
+		exclusive = 1,
+		hideOnEscape = 0,
+		whileDead = 1,
+	}
+end
+
+local function EMASettingsTreeSort( a, b )
+	local aText = ""
+	local bText = ""
+	local aEMAOrder = 0
+	local bEMAOrder = 0
+	if a ~= nil then
+		aText = a.text
+		aEMAOrder = a.EMAOrder
+	end
+	if b ~= nil then
+		bText = b.text
+		bEMAOrder = b.EMAOrder
+	end
+	if aText == L["EMA"] or bText == L["EMA"] then
+		if aText == L["EMA"] then
+			return true
+		end
+		if bText == L["EMA"] then
+			return false
+		end
+	end
+	if aEMAOrder == bEMAOrder then
+		return aText < bText
+	end
+	return aEMAOrder < bEMAOrder
+end
+
+local function EMATreeGroupTreeGetParent( parentName )
+	local parent
+	for index, tableInfo in ipairs( EMAPrivate.SettingsFrame.Tree.Data ) do
+		if tableInfo.value == parentName then
+			parent = tableInfo
+		end
+	end
+	return parent
+end
+
+local function EMAAddModuleToSettings( childName, parentName, moduleIcon, order, moduleFrame )
+	-- 	childName is the parentName then make the child the parent.
+	if childName == parentName then
+		local parent = EMATreeGroupTreeGetParent( parentName )
+		if parent == nil then
+			table.insert( EMAPrivate.SettingsFrame.Tree.Data, { value = childName, text = childName, EMAOrder = order, icon = moduleIcon } )
+			table.sort( EMAPrivate.SettingsFrame.Tree.Data, EMASettingsTreeSort )
+			EMAPrivate.SettingsFrame.Tree.ModuleFrames[childName] = moduleFrame
+		end
+
+	else
+	local parent = EMATreeGroupTreeGetParent( parentName )
+	if parent == nil then
+		table.insert( EMAPrivate.SettingsFrame.Tree.Data, { value = parentName, text = parentName, EMAOrder = order } )
+	end
+	local parent = EMATreeGroupTreeGetParent( parentName )
+	if parent.children == nil then
+		parent.children = {}
+	end
+		table.insert( parent.children, { value = childName, text = childName, EMAOrder = order, icon = moduleIcon } )
+		table.sort( EMAPrivate.SettingsFrame.Tree.Data, EMASettingsTreeSort )
+		table.sort( parent.children, EMASettingsTreeSort )
+		EMAPrivate.SettingsFrame.Tree.ModuleFrames[childName] = moduleFrame
+	end
+end
+
+
+
+local function EMAModuleSelected( tree, event, treeValue, selected )
+	--EMA:Print("test", tree, event, treeValue, selected)
+	local parentValue, value = strsplit( "\001", treeValue )
+	if tree == nil and event == nil then
+		-- Came from chat command.
+		value = treeValue
+	end
+	if value == nil then
+		value = parentValue
+	end
+	EMAPrivate.SettingsFrame.Widget:Show()
+	if EMAPrivate.SettingsFrame.Tree.CurrentChild ~= nil then
+		EMAPrivate.SettingsFrame.Tree.CurrentChild.frame:Hide()
+		EMAPrivate.SettingsFrame.Tree.CurrentChild = nil
+	end
+	for moduleValue, moduleFrame in pairs( EMAPrivate.SettingsFrame.Tree.ModuleFrames ) do
+		if 	moduleValue == value then
+			moduleFrame:SetParent( EMAPrivate.SettingsFrame.WidgetTree )
+			moduleFrame:SetWidth( EMAPrivate.SettingsFrame.WidgetTree.content:GetWidth() or 0 )
+			moduleFrame:SetHeight( EMAPrivate.SettingsFrame.WidgetTree.content:GetHeight() or 0 )
+			moduleFrame.frame:SetAllPoints()
+			moduleFrame.frame:Show()
+			EMAPrivate.SettingsFrame.Tree.CurrentChild = moduleFrame
+			if value == L["OPTIONS"] then
+				LibStub( "AceConfigDialog-3.0" ):Open( EMA.moduleName..L["OPTIONS"], moduleFrame )
+			end
+			return
+		end
+	end
+end
+EMAPrivate.SettingsFrame.Tree = {}
+EMAPrivate.SettingsFrame.Tree.Data = {}
+EMAPrivate.SettingsFrame.Tree.ModuleFrames = {}
+EMAPrivate.SettingsFrame.Tree.CurrentChild = nil
+EMAPrivate.SettingsFrame.Tree.Add = EMAAddModuleToSettings
+EMAPrivate.SettingsFrame.Tree.ButtonClick = EMAModuleSelected
+EMAPrivate.SettingsFrame.WidgetTree:SetTree( EMAPrivate.SettingsFrame.Tree.Data )
+EMAPrivate.SettingsFrame.WidgetTree:SetCallback( "OnClick", EMAPrivate.SettingsFrame.Tree.ButtonClick )
+EMAPrivate.SettingsFrame.Widget:Hide()
+--table.insert( UISpecialFrames, "EMASettingsWindowsFrame" )
+
+-- Settings - the values to store and their defaults for the settings database.
+EMA.settings = {
+	global = {
+		['**'] = {
+			showStartupMessage8000 = false,
+			showStartupMessage2000 = true,
+			showStartupMessageClassic = true,
+		},
+	 },
+	profile = {
+	},
+}
+
+-- Configuration.
+local function GetConfiguration()
+	local configuration = {
+		name = "EMA",
+		handler = EMA,
+		type = 'group',
+		childGroups  = "tab",
+		get = "ConfigurationGetSetting",
+		set = "ConfigurationSetSetting",
+		args = {
+			config = {
+				type = "input",
+				name = L["OPEN_CONFIG"],
+				desc = L["OPEN_CONFIG_HELP"],
+				usage = "/ema config",
+				get = false,
+				set = "",
+				order = 5,
+				guiHidden = true,
+			},
+			push = {
+				type = "input",
+				name = L["PUSH_SETTINGS"],
+				desc = L["PUSH_SETTINGS_INFO"],
+				usage = "/ema push",
+				get = false,
+				set = "SendSettingsAllModules",
+				order = 4,
+				guiHidden = true,
+			},
+			resetsettingsframe = {
+				type = "input",
+				name = L["RESET_SETTINGS_FRAME"],
+				desc = L["RESET_SETTINGS_FRAME"],
+				usage = "/ema resetsettingsframe",
+				get = false,
+				set = "ResetSettingsFrame",
+				order = 5,
+				guiHidden = true,
+			},
+		},
+	}
+	return configuration
+end
+
+-- Get a settings value.
+function EMA:ConfigurationGetSetting( key )
+	return EMA.db[key[#key]]
+end
+
+-- Set a settings value.
+function EMA:ConfigurationSetSetting( key, value )
+	EMA.db[key[#key]] = value
+end
+
+local function DebugMessage( ... )
+	EMA:Print( ... )
+end
+
+--WOW BetaBuild!
+local function isBetaBuild()
+	local _, _, _, tocversion = GetBuildInfo()
+	-- Build For BFA 8.0.1 2018
+	if tocversion >= 80000 then
+		return true
+	else
+		return  false
+	end
+end
+
+--Ema Alpha
+local function isEmaAlphaBuild()
+	local EMAVersion = GetAddOnMetadata("EMA", "version")
+	-- EMA Alpha Build
+	local Alpha = EMAVersion:find( "Alpha" )
+	if Alpha then
+		return true
+	else
+		return false
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Module management.
+-------------------------------------------------------------------------------------------------------------
+
+-- Register a EMA module.
+local function RegisterModule( moduleAddress, moduleName )
+	if EMA.registeredModulesByName == nil then
+		EMA.registeredModulesByName = {}
+	end
+	if EMA.registeredModulesByAddress == nil then
+		EMA.registeredModulesByAddress = {}
+	end
+	EMA.registeredModulesByName[moduleName] = moduleAddress
+	EMA.registeredModulesByAddress[moduleAddress] = moduleName
+end
+
+local function UnRegisterModule( moduleAddress, moduleName )
+	print("unRegister", moduleAddress, moduleName )
+	if EMA.registeredModulesByName == nil then
+		EMA.registeredModulesByName = {}
+	end
+	if EMA.registeredModulesByAddress == nil then
+		EMA.registeredModulesByAddress = {}
+	end
+
+	EMA.registeredModulesByName[moduleName] = nil
+	EMA.registeredModulesByAddress[moduleAddress] = nil
+end
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings sending and receiving.
+-------------------------------------------------------------------------------------------------------------
+
+-- Send the settings for the module specified (using its address) to other EMA Team characters.
+local function SendSettings( moduleAddress, settings )
+	-- Get the name of the module.
+	local moduleName = EMA.registeredModulesByAddress[moduleAddress]
+	-- Send the settings identified by the module name.
+	EMAPrivate.Communications.SendSettings( moduleName, settings )
+end
+
+-- Settings are received, pass them to the relevant module.
+local function OnSettingsReceived( sender, moduleName, settings )
+	sender = EMAUtilities:AddRealmToNameIfMissing( sender )
+	--EMA:Print("onsettings", sender, moduleName )
+	-- Get the address of the module.
+	local moduleAddress = EMA.registeredModulesByName[moduleName]
+	-- can not receive a message from a Module not Loaded so ignore it. Better tell them its not loaded --ebony.
+	if moduleAddress == nil then
+		EMA:Print(L["MODULE_NOT_LOADED"], moduleName)
+		return
+	else
+	-- loaded? Pass the module its settings.
+		moduleAddress:EMAOnSettingsReceived( sender, settings )
+	end
+end
+
+function EMA:SendSettingsAllModules()
+	EMA:Print( "Sending settings for all modules." )
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		EMA:Print( "Sending settings for: ", moduleName )
+		moduleAddress:EMASendSettings()
+	end
+end
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Commands sending and receiving.
+-------------------------------------------------------------------------------------------------------------
+
+-- Send a command for the module specified (using its address) to other EMA Team characters.
+local function SendCommandToTeam( moduleAddress, commandName, ... )
+	-- Get the name of the module.
+	local moduleName = EMA.registeredModulesByAddress[moduleAddress]
+	-- Send the command identified by the module name.
+	if moduleAddress == nil then
+		EMA:Print(L["MODULE_NOT_LOADED"], moduleName)
+		return
+	else
+	EMAPrivate.Communications.SendCommandAll( moduleName, commandName, ... )
+	end
+end
+
+-- Send a command for the module specified (using its address) to the master character.
+local function SendCommandToMaster( moduleAddress, commandName, ... )
+	-- Get the name of the module.
+	local moduleName = EMA.registeredModulesByAddress[moduleAddress]
+	-- Send the command identified by the module name.
+	if moduleAddress == nil then
+		EMA:Print(L["MODULE_NOT_LOADED"], moduleName)
+		return
+	else
+	EMAPrivate.Communications.SendCommandMaster( moduleName, commandName, ... )
+	end
+end
+
+local function SendCommandToToon( moduleAddress, characterName, commandName, ... )
+	-- Get the name of the module.
+	local moduleName = EMA.registeredModulesByAddress[moduleAddress]
+	-- Send the command identified by the module name.
+	if moduleAddress == nil then
+		EMA:Print(L["MODULE_NOT_LOADED"], moduleName)
+		return
+	else
+	EMAPrivate.Communications.SendCommandToon( moduleName, characterName, commandName, ... )
+	end
+end
+
+-- A command is received, pass it to the relevant module.
+local function OnCommandReceived( sender, moduleName, commandName, ... )
+	sender = EMAUtilities:AddRealmToNameIfMissing( sender )
+	-- Get the address of the module.
+	local moduleAddress = EMA.registeredModulesByName[moduleName]
+	-- Pass the module its settings.
+	if moduleAddress == nil then
+		EMA:Print(L["MODULE_NOT_LOADED"], moduleName)
+		return
+	else
+		moduleAddress:EMAOnCommandReceived( sender, commandName, ... )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Core Profile Support.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:FireBeforeProfileChangedEvent()
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		if moduleName ~= EMA.moduleName then
+			moduleAddress:BeforeEMAProfileChanged()
+		end
+	end
+end
+
+function EMA:CanChangeProfileForModule( moduleName )
+	if (moduleName ~= EMA.moduleName) and (moduleName ~= EMA.teamModuleName) then
+		return true
+	end
+	return false
+end
+
+function EMA:FireOnProfileChangedEvent( moduleAddress )
+	moduleAddress.db = moduleAddress.completeDatabase.profile
+	moduleAddress:OnEMAProfileChanged()
+end
+
+function EMA:OnProfileChanged( event, database, newProfileKey, ... )
+	EMA:Print( "Profile changed - iterating all modules.")
+	EMA:FireBeforeProfileChangedEvent()
+	-- Do the team module before all the others.
+	local teamModuleAddress = EMA.registeredModulesByName[EMA.teamModuleName]
+	EMA:Print( "Changing profile: ", EMA.teamModuleName )
+	teamModuleAddress.completeDatabase:SetProfile( newProfileKey )
+	EMA:FireOnProfileChangedEvent( teamModuleAddress )
+	-- Do the other modules.
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		if EMA:CanChangeProfileForModule( moduleName ) == true then
+			EMA:Print( L["CHANGING_PROFILE"] , moduleName )
+			moduleAddress.completeDatabase:SetProfile( newProfileKey )
+			EMA:FireOnProfileChangedEvent( moduleAddress )
+		end
+	end
+end
+
+function EMA:OnProfileCopied( event, database, sourceProfileKey )
+	EMA:Print( "Profile copied - iterating all modules." )
+	EMA:FireBeforeProfileChangedEvent()
+	-- Do the team module before all the others.
+	local teamModuleAddress = EMA.registeredModulesByName[EMA.teamModuleName]
+	EMA:Print( L["COPYING_PROFILE"], EMA.teamModuleName )
+	teamModuleAddress.completeDatabase:CopyProfile( sourceProfileKey, true )
+	EMA:FireOnProfileChangedEvent( teamModuleAddress )
+	-- Do the other modules.
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		if EMA:CanChangeProfileForModule( moduleName ) == true then
+			EMA:Print( L["COPYING_PROFILE"], moduleName )
+			moduleAddress.completeDatabase:CopyProfile( sourceProfileKey, true )
+			EMA:FireOnProfileChangedEvent( moduleAddress )
+		end
+	end
+end
+
+function EMA:OnProfileReset( event, database )
+	EMA:Print( L["PROFILE_RESET"] )
+	EMA:FireBeforeProfileChangedEvent()
+	-- Do the team module before all the others.
+	local teamModuleAddress = EMA.registeredModulesByName[EMA.teamModuleName]
+	EMA:Print( L["RESETTING_PROFILE"], EMA.teamModuleName )
+	teamModuleAddress.completeDatabase:ResetProfile()
+	EMA:FireOnProfileChangedEvent( teamModuleAddress )
+	-- Do the other modules.
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		if EMA:CanChangeProfileForModule( moduleName ) == true then
+			EMA:Print( L["RESETTING_PROFILE"], moduleName )
+			moduleAddress.completeDatabase:ResetProfile()
+			EMA:FireOnProfileChangedEvent( moduleAddress )
+		end
+	end
+end
+
+function EMA:OnProfileDeleted( event, database, profileKey )
+	EMA:Print( L["PROFILE_DELETED"] )
+	EMA:FireBeforeProfileChangedEvent()
+	-- Do the team module before all the others.
+	local teamModuleAddress = EMA.registeredModulesByName[EMA.teamModuleName]
+	EMA:Print( L["DELETING_PROFILE"], EMA.teamModuleName )
+	teamModuleAddress.completeDatabase:DeleteProfile( profileKey, true )
+	EMA:FireOnProfileChangedEvent( teamModuleAddress )
+	-- Do the other modules.
+	for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+		if EMA:CanChangeProfileForModule( moduleName ) == true then
+			EMA:Print( L["DELETING_PROFILE"], moduleName )
+			moduleAddress.completeDatabase:DeleteProfile( profileKey, true )
+			EMA:FireOnProfileChangedEvent( moduleAddress )
+		end
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Core Initialization.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialize the addon.
+function EMA:OnInitialize()
+	-- Initialise the popup dialogs.
+	InitializePopupDialogs()
+	-- Tables to hold registered modules - lookups by name and by address.
+	-- By name is used for communication between clients and by address for communication between addons on the same client.
+	EMA.registeredModulesByName = {}
+	EMA.registeredModulesByAddress = {}
+	-- Create the settings database supplying the settings values along with defaults.
+    EMA.completeDatabase = LibStub( "AceDB-3.0" ):New( EMA.settingsDatabaseName, EMA.settings )
+	EMA.completeDatabase.RegisterCallback( EMA, "OnProfileChanged", "OnProfileChanged" )
+	EMA.completeDatabase.RegisterCallback( EMA, "OnProfileCopied", "OnProfileCopied" )
+	EMA.completeDatabase.RegisterCallback( EMA, "OnProfileReset", "OnProfileReset" )
+	EMA.completeDatabase.RegisterCallback( EMA, "OnProfileDeleted", "OnProfileDeleted" )
+
+	EMA.db = EMA.completeDatabase.profile
+	EMA.db.global = EMA.completeDatabase.global
+	-- Create the settings.
+	LibStub( "AceConfig-3.0" ):RegisterOptionsTable(
+		EMA.moduleName,
+		GetConfiguration()
+	)
+	-- Create the settings frame.
+	EMA:CoreSettingsCreate()
+	EMA.settingsFrame = EMA.settingsControl.widgetSettings.frame
+	-- TODO DO WE NEED THIS ??????
+	--[[
+	-- Blizzard options frame.
+	local frame = CreateFrame( "Frame" )
+	frame.name = L["EMA"]
+	local button = CreateFrame( "Button", nil, frame, "OptionsButtonTemplate" )
+	button:SetPoint( "CENTER" )
+	button:SetText( "/EMA" )
+	button:SetScript( "OnClick", EMA.LoadEMASettings )
+	InterfaceOptions_AddCategory( frame )
+	]]
+	-- Create the settings profile support.
+	LibStub( "AceConfig-3.0" ):RegisterOptionsTable(
+		EMA.moduleName..L["OPTIONS"],
+		LibStub( "AceDBOptions-3.0" ):GetOptionsTable( EMA.completeDatabase )
+	)
+	local profileContainerWidget = AceGUI:Create( "ScrollFrame" )
+	profileContainerWidget:SetLayout( "Fill" )
+	-- We need this to make it a working Module
+	local order  = 10
+	EMAPrivate.SettingsFrame.Tree.Add( L["OPTIONS"], L["OPTIONS"], EMA.pofileIcon, order, profileContainerWidget )
+
+	-- Register the core as a module.
+	RegisterModule( EMA, EMA.moduleName )
+	-- Register the chat command.
+	EMA:RegisterChatCommand( EMA.chatCommand, "EMAChatCommand" )
+end
+
+function EMA:LoadEMAModule( moduleName )
+	local loaded, reason = LoadAddOn( moduleName )
+	if not loaded then
+		if reason ~= "DISABLED" and reason ~= "MISSING" then
+			EMA:Print(L["Failed_LOAD_MODULE"]..moduleName.."' ["..reason.."]." )
+		end
+	end
+end
+
+function EMA:CoreSettingsCreateInfo( top )
+	-- Get positions and dimensions.
+	local buttonPushAllSettingsWidth = 200
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local checkBoxHeight = EMAHelperSettings:GetCheckBoxHeight()
+	local radioBoxHeight = EMAHelperSettings:GetRadioBoxHeight()
+	local labelHeight = EMAHelperSettings:GetLabelHeight()
+	local labelContinueHeight = EMAHelperSettings:GetContinueLabelHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local indent = horizontalSpacing * 10
+	local indentContinueLabel = horizontalSpacing * 18
+	local indentSpecial = indentContinueLabel + 9
+	local checkBoxThirdWidth = (headingWidth - indentContinueLabel) / 3
+	local column1Left = left
+	local column2Left = column1Left + checkBoxThirdWidth + horizontalSpacing - 35
+	local column1LeftIndent = left + indentContinueLabel
+	local column2LeftIndent = column1LeftIndent + checkBoxThirdWidth + horizontalSpacing
+	local column3LeftIndent = column2LeftIndent + checkBoxThirdWidth + horizontalSpacing
+	local movingTop = top
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	movingTop = movingTop - headingHeight
+	--Main Heading
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["STATUSTEXT"], movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.labelInformation1 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["ME"]
+	)
+	movingTop = movingTop + movingTop * 2
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["RELEASE_NOTES"]..GetAddOnMetadata("EMA-Classic", "version") , movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.labelInformation10 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT1"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation11 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT2"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation12 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT3"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation13	= EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT4"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation14 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT5"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation15 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT6"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation16 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT7"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation17 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT8"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation18 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT9"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation19 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEXT10"]
+	)
+	--movingTop = movingTop - labelContinueHeight
+	-- Useful websites Heading
+	movingTop = movingTop - labelContinueHeight * 2
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["WEBSITES"], movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.labelInformation30 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEMP_WEBSITE1"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation21 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["ME_TWITTER"]
+
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation22 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["D-B"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation23 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["ISB"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation24 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEMP_WEBSITE2"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation25 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["TEMP_WEBSITE3"]
+	)
+	-- Special thanks Heading
+	movingTop = movingTop - buttonHeight
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["SPECIAL_THANKS"], movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.labelInformation20 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["THANKS1"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation21 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["THANKS2"]
+
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation22 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["THANKS3"]
+	)
+	--CopyRight heading
+	movingTop = movingTop - labelContinueHeight * 4
+	EMA.settingsControl.labelInformation40 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["COPYRIGHT"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	EMA.settingsControl.labelInformation41 = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column2Left,
+		movingTop,
+		L["COPYRIGHTTWO"]
+	)
+	movingTop = movingTop - labelContinueHeight
+	return movingTop
+end
+
+function EMA:CoreSettingsCreate()
+	EMA.settingsControl = {}
+	-- Create the settings panel.
+	EMAHelperSettings:CreateSettings(
+		EMA.settingsControl,
+		EMA.moduleDisplayName,
+		EMA.parentDisplayName,
+		EMA.SendSettingsAllModules,
+		EMA.moduleIcon,
+		EMA.moduleOrder
+	)
+	local bottomOfInfo = EMA:CoreSettingsCreateInfo( EMAHelperSettings:TopOfSettings() )
+	EMA.settingsControl.widgetSettings.content:SetHeight( -bottomOfInfo )
+end
+
+-- Send core settings.
+function EMA:EMASendSettings()
+	EMAPrivate.Communications.SendSettings( EMA.moduleName, EMA.db )
+end
+
+function EMA:OnEMAProfileChanged()
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsRefresh()
+end
+
+-- Core settings received.
+function EMA:EMAOnSettingsReceived( characterName, settings )
+	--Checks character is not the the character that send the settings. Now checks the character has a realm on there name to match EMA team list.
+	--characterName = EMAUtilities:AddRealmToNameIfMissing( characterName )
+	if characterName ~= EMA.characterName then
+		-- Update the settings.
+        -- TODO: What is this minimap icon?
+		EMA.db.showMinimapIcon = settings.showMinimapIcon
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		-- Tell the player.
+		EMA:Print( L["SETTINGS_RECEIVED_FROM_A"]( characterName ) )
+	end
+end
+
+--[[
+function EMA:LoadEMASettings()
+	InterfaceOptionsFrameCancel_OnClick()
+	HideUIPanel( GameMenuFrame )
+	EMA:EMAChatCommand( "" )
+end
+]]
+
+--	Does the Chat Command Exist
+local function DoesTheChatCommandExist( configuration, command )
+	local exist = false
+	for key, info in pairs( configuration ) do
+		if info.type == "input" then
+			if key == command then
+				exist = true
+				break
+			end
+		end
+	end
+	return exist
+end
+
+-- Handle the chat command.
+function EMA:EMAChatCommand( inputBefore )
+	input = string.lower( inputBefore )
+	--EMA:Print("test", input )
+	local inputString, tag = strsplit( " ", inputBefore )
+	local CommandExist = DoesTheChatCommandExist( GetConfiguration().args, inputString )
+	if input == "config" then
+		if InCombatLockdown() then
+			print( L["CANNOT_OPEN_IN_COMBAT"] )
+		return
+	end
+		-- Show Config
+		EMAPrivate.SettingsFrame.Widget:Show()
+		EMAPrivate.SettingsFrame.WidgetTree:SelectByValue( L["NEWS"] )
+		EMAPrivate.SettingsFrame.Tree.ButtonClick( nil, nil, EMA.moduleDisplayName, false)
+	elseif CommandExist then
+		--Command Found now Handle IT!
+		--print("Command Found", input )
+		LibStub( "AceConfigCmd-3.0" ):HandleCommand( EMA.chatCommand, EMA.moduleName, input )
+	else
+		-- hell knows what to do so HELP!!!
+		--print("No found Command Found HELP", input )
+		for key, info in pairs( GetConfiguration().args ) do
+			if info.type == "input" then
+				print("|cFFFFFF00"..info.usage, "|cFFFFFFFF".." [ "..info.desc.." ]" )
+			end
+		end
+		print( L["MODULE_LIST"] )
+		for moduleName, moduleAddress in pairs( EMA.registeredModulesByName ) do
+			print("|cFFFFFF00/"..EMA.chatCommand.."-"..moduleName )
+		end
+	end
+end
+
+function EMA:ResetSettingsFrame()
+	EMA:Print( L["FRAME_RESET"] )
+	EMAPrivate.SettingsFrame.Widget:SetPoint("TOPLEFT", 0, 0)
+	EMAPrivate.SettingsFrame.Widget:SetWidth(900)
+	EMAPrivate.SettingsFrame.Widget:SetHeight(800)
+	EMAPrivate.SettingsFrame.Widget:Show()
+end
+
+function EMA:SettingsTestBox( event, checked)
+	print("test", checked , EMA.db.testBox)
+	EMA.db.testBox = checked
+	EMA:SettingsRefresh()
+
+end
+
+-- Functions available from EMA Core for other EMA internal objects.
+EMAPrivate.Core.RegisterModule = RegisterModule
+EMAPrivate.Core.UnRegisterModule = UnRegisterModule
+EMAPrivate.Core.SendSettings = SendSettings
+EMAPrivate.Core.OnSettingsReceived = OnSettingsReceived
+EMAPrivate.Core.SendCommandToTeam = SendCommandToTeam
+EMAPrivate.Core.SendCommandToMaster = SendCommandToMaster
+EMAPrivate.Core.SendCommandToToon = SendCommandToToon
+EMAPrivate.Core.OnCommandReceived = OnCommandReceived
+EMAPrivate.Core.isBetaBuild = isBetaBuild
+EMAPrivate.Core.isEmaAlphaBuild = isEmaAlphaBuild
+EMAPrivate.Core.SendSettingsAllModules = EMA.SendSettingsAllModules
\ No newline at end of file
diff --git a/Core/Message-Classic.lua b/Core/Message-Classic.lua
new file mode 100644
index 0000000..912c657
--- /dev/null
+++ b/Core/Message-Classic.lua
@@ -0,0 +1,1000 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+-- THIS FILE NEED A GOOD REWIRE ONEDAY, AND A PAIN IN THE NECK TO USE.........
+
+
+-- Create the addon using AceAddon-3.0 and embed some libraries.
+local EMA = LibStub( "AceAddon-3.0" ):NewAddon(
+	"Message",
+	"Module-1.0",
+	"AceConsole-3.0",
+	"AceEvent-3.0",
+	"AceHook-3.0"
+)
+
+-- Load libraries.
+local EMAUtilities = LibStub:GetLibrary( "EbonyUtilities-1.0" )
+local EMAHelperSettings = LibStub:GetLibrary( "EMAHelperSettings-1.0" )
+local Media = LibStub("LibSharedMedia-3.0")
+
+-- Built in Sounds
+Media:Register("sound", "EMA: RaidWarning", "Sound\\interface\\RaidWarning.ogg")
+
+
+-- Constants and Locale for this module.
+EMA.moduleName = "Message"
+EMA.settingsDatabaseName = "MessageProfileDB"
+EMA.chatCommand = "ema-message"
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+EMA.parentDisplayName = L["OPTIONS"]
+EMA.moduleDisplayName = L["MESSAGE_DISPLAY"]
+-- Icon
+EMA.moduleIcon = "Interface\\Addons\\EMA-Classic\\Media\\ChatIcon.tga"
+-- order
+EMA.moduleOrder = 80
+
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Message area management.
+-------------------------------------------------------------------------------------------------------------
+
+-- areas = {}
+-- areas["areaname"].type
+-- areas["areaname"].tag
+-- areas["areaname"].channelName
+-- areas["areaname"].channelPassword
+-- areas["areaname"].chatWindowName
+-- areas["areaname"].areaOnScreenName
+-- areas["areaname"].soundToPlay
+
+-- Message area types.
+EMA.AREA_TYPE_DEFAULT_CHAT = 1
+--EMA.AREA_TYPE_SPECIFIC_CHAT = 2
+EMA.AREA_TYPE_WHISPER = 3
+EMA.AREA_TYPE_PARTY = 4
+EMA.AREA_TYPE_GUILD = 5
+EMA.AREA_TYPE_GUILD_OFFICER = 6
+EMA.AREA_TYPE_RAID = 7
+EMA.AREA_TYPE_RAID_WARNING = 8
+--EMA.AREA_TYPE_CHANNEL = 9
+--EMA.AREA_TYPE_PARROT = 10
+--EMA.AREA_TYPE_MSBT = 11
+EMA.AREA_TYPE_MUTE = 12
+
+-- Message area types names and uses information.
+EMA.areaTypes = {}
+-- Default chat window.
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT] = {}
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].name = L["DEFAULT_CHAT_WINDOW"]
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].usesTag = true
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].mustBeWired = true
+EMA.areaTypes[EMA.AREA_TYPE_DEFAULT_CHAT].usesSound = true
+-- Specific chat window.
+--[[
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT] = {}
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].name = L["Specific Chat Window"]
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].usesTag = true
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].usesChatWindowName = true
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].mustBeWired = true
+EMA.areaTypes[EMA.AREA_TYPE_SPECIFIC_CHAT].usesSound = true
+]]--
+-- Whisper.
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER] = {}
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].name = L["WHISPER"]
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].usesTag = true
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].mustBeWired = true
+EMA.areaTypes[EMA.AREA_TYPE_WHISPER].usesSound = true
+-- Party.
+EMA.areaTypes[EMA.AREA_TYPE_PARTY] = {}
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].name = L["PARTY"]
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_PARTY].usesSound = true
+-- Guild.
+EMA.areaTypes[EMA.AREA_TYPE_GUILD] = {}
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].name = L["GUILD"]
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD].usesSound = true
+-- Guild Officer.
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER] = {}
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].name = L["GUILD_OFFICER"]
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_GUILD_OFFICER].usesSound = true
+-- Raid.
+EMA.areaTypes[EMA.AREA_TYPE_RAID] = {}
+EMA.areaTypes[EMA.AREA_TYPE_RAID].name = L["RAID"]
+EMA.areaTypes[EMA.AREA_TYPE_RAID].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID].usesSound = true
+-- Raid Warning.
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING] = {}
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].name = L["RAID_WARNING"]
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].usesTag = true
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].mustBeWired = true
+EMA.areaTypes[EMA.AREA_TYPE_RAID_WARNING].usesSound = true
+-- Private Channel.
+--[[
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL] = {}
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].name = L["Channel"]
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].usesChannel = true
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_CHANNEL].usesSound = true
+--]]
+-- Mute.
+EMA.areaTypes[EMA.AREA_TYPE_MUTE] = {}
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].name = L["MUTE"]
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].usesTag = false
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].usesChannel = false
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].usesChatWindowName = false
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].usesScreen = false
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].mustBeWired = false
+EMA.areaTypes[EMA.AREA_TYPE_MUTE].usesSound = false
+
+-- Settings - the values to store and their defaults for the settings database.
+EMA.settings = {
+	profile = {
+		["areas"] = {
+			{
+				["type"] = 1,
+				["name"] = L["DEFAULT_MESSAGE"],
+				["tag"] = EMAPrivate.Tag.MasterTag(),
+			},
+			{
+				["type"] = 8,
+				["name"] = L["DEFAULT_WARNING"],
+				["tag"] = EMAPrivate.Tag.MasterTag(),
+				["soundToPlay"] = "EMA: RaidWarning",
+			},
+			{
+				["type"] = 12,
+				["name"] = L["MUTE_POFILE"],
+			},
+		},
+	},
+}
+
+ EMA.simpleAreaList = {}
+
+-- Configuration.
+function EMA:GetConfiguration()
+	local configuration = {
+		name = EMA.moduleDisplayName,
+		handler = EMA,
+		type = "group",
+		get = "EMAConfigurationGetSetting",
+		set = "EMAConfigurationSetSetting",
+		args = {
+			config = {
+				type = "input",
+				name = L["OPEN_CONFIG"],
+				desc = L["OPEN_CONFIG_HELP"],
+				usage = "/ema-message config",
+				get = false,
+				set = "",
+			},
+			push = {
+				type = "input",
+				name = L["PUSH_SETTINGS"],
+				desc = L["PUSH_SETTINGS_INFO"],
+				usage = "/ema-message push",
+				get = false,
+				set = "EMASendSettings",
+			},
+		},
+	}
+	return configuration
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Command this module sends.
+-------------------------------------------------------------------------------------------------------------
+
+EMA.COMMAND_MESSAGE = "EMAMessageMessage"
+
+-------------------------------------------------------------------------------------------------------------
+-- Messages module sends.
+-------------------------------------------------------------------------------------------------------------
+
+-- Master changed, parameter: new master name.
+EMA.MESSAGE_MESSAGE_AREAS_CHANGED = "EMAMessageMessageAreasChanged"
+
+-------------------------------------------------------------------------------------------------------------
+-- Constants used by module.
+-------------------------------------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Populate.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:BeforeEMAProfileChanged()
+end
+
+function EMA:OnEMAProfileChanged()
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsRefresh()
+	-- Update the settings area list.
+	EMA:SettingsAreaListScrollRefresh()
+end
+
+-- Settings received.
+function EMA:EMAOnSettingsReceived( characterName, settings )
+	if characterName ~= EMA.characterName then
+		-- Update the settings.
+		EMA.db.areas = EMAUtilities:CopyTable( settings.areas )
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		EMA:SendMessage( EMA.MESSAGE_MESSAGE_AREAS_CHANGED )
+		-- Tell the player.
+		EMA:Print( L["SETTINGS_RECEIVED_FROM_A"]( characterName ) )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Area management.
+-------------------------------------------------------------------------------------------------------------
+
+local function MessageAreaList()
+	EMAUtilities:ClearTable( EMA.simpleAreaList )
+	for index, area in ipairs( EMA.db.areas ) do
+		EMA.simpleAreaList[area.name] = area.name
+	end
+	table.sort( EMA.simpleAreaList )
+	return EMA.simpleAreaList
+end
+
+local function GetAreaByName( areaName )
+	for index, area in ipairs( EMA.db.areas ) do
+		if area.name == areaName then
+			return area
+		end
+	end
+	return nil
+end
+
+local function GetAreaAtPosition( position )
+	return EMA.db.areas[position]
+end
+
+local function SetAreaAtPosition( position, areaInformation )
+	EMA.db.areas[position] = areaInformation
+end
+
+local function GetAreaListMaxPosition()
+	return #EMA.db.areas
+end
+
+local function DoesAreaListContainArea( name )
+	local containsArea = false
+	for index, area in ipairs( EMA.db.areas ) do
+		if area.name == name then
+			containsArea = true
+			break
+		end
+	end
+	return containsArea
+end
+
+local function AddArea( name )
+	if DoesAreaListContainArea( name ) == false then
+		-- Add a new area.
+		local newArea = {}
+		newArea.name = name
+		newArea.type = EMA.AREA_TYPE_DEFAULT_CHAT
+		table.insert( EMA.db.areas, newArea )
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		EMA:SendMessage( EMA.MESSAGE_MESSAGE_AREAS_CHANGED )
+	end
+end
+
+local function RemoveArea( name )
+	if DoesAreaListContainArea( name ) == true then
+		local areaIndex = 0
+		for index, area in ipairs( EMA.db.areas ) do
+			if area.name == name then
+				areaIndex = index
+				break
+			end
+		end
+		if areaIndex ~= 0 then
+			table.remove( EMA.db.areas, areaIndex )
+			-- Send a message to any listeners that the message areas have changed.
+			EMA:SendMessage( EMA.MESSAGE_MESSAGE_AREAS_CHANGED )
+		end
+	end
+end
+
+function EMA:AddAreaGUI( name )
+	AddArea( name )
+	EMA:SettingsAreaListScrollRefresh()
+end
+
+function EMA:RemoveAreaGUI()
+	local area = GetAreaAtPosition( EMA.settingsControl.areaListHighlightRow )
+	RemoveArea( area.name )
+	EMA.settingsControl.areaListHighlightRow = 1
+	EMA:SettingsAreaListScrollRefresh()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+local function SettingsCreateAreaList()
+	-- Position and size constants.
+	local areaListButtonControlWidth = 125
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local top = EMAHelperSettings:TopOfSettings()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local areaListWidth = headingWidth
+	-- Team list internal variables (do not change).
+	EMA.settingsControl.areaListHighlightRow = 1
+	EMA.settingsControl.areaListOffset = 1
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	top = top - headingHeight
+	-- Create a heading.
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["MESSAGE_AREA_LIST"], top, false )
+	-- Create an area list frame.
+
+	local list = {}
+	list.listFrameName = "EMAMessageSettingsAreaListFrame"
+	list.parentFrame = EMA.settingsControl.widgetSettings.content
+	list.listTop = top - headingHeight
+	list.listLeft = left
+	list.listWidth = areaListWidth
+	list.rowHeight = 20
+	list.rowsToDisplay = 8
+	list.columnsToDisplay = 2
+	list.columnInformation = {}
+	list.columnInformation[1] = {}
+	list.columnInformation[1].width = 60
+	list.columnInformation[1].alignment = "LEFT"
+	list.columnInformation[2] = {}
+	list.columnInformation[2].width = 40
+	list.columnInformation[2].alignment = "LEFT"
+	list.scrollRefreshCallback = EMA.SettingsAreaListScrollRefresh
+	list.rowClickCallback = EMA.SettingsAreaListRowClick
+	EMA.settingsControl.areaList = list
+	EMAHelperSettings:CreateScrollList( EMA.settingsControl.areaList )
+	-- Position and size constants (once list height is known).
+	local bottomOfList = top - headingHeight - list.listHeight - verticalSpacing
+	local bottomOfSection = bottomOfList - verticalSpacing - buttonHeight - verticalSpacing
+	-- Create buttons.
+	EMA.settingsControl.areaListButtonAdd = EMAHelperSettings:CreateButton(
+		EMA.settingsControl,
+		areaListButtonControlWidth,
+		left,
+		bottomOfList,
+		L["ADD"],
+		EMA.SettingsAddClick,
+		L["ADD_MSG_HELP"]
+	)
+	EMA.settingsControl.areaListButtonRemove = EMAHelperSettings:CreateButton(
+		EMA.settingsControl,
+		areaListButtonControlWidth,
+		left + horizontalSpacing + areaListButtonControlWidth,
+		bottomOfList,
+		L["REMOVE"],
+		EMA.SettingsRemoveClick,
+		L["REMOVE_MSG_HELP"]
+	)
+
+	return bottomOfSection
+end
+
+local function SettingsCreateAreaTypes( top )
+	local areaListButtonControlWidth = 125
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local dropdownHeight = EMAHelperSettings:GetDropdownHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local halfWidth = (headingWidth - (horizontalSpacing  * 3)) / 2
+	local column1Left = left
+	local column2Left = left + halfWidth + (horizontalSpacing * 3)
+	local areaConfigurationTop = top - headingHeight
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	top = top - headingHeight
+	--Main Heading
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["MESSAGE_AREA_CONFIGURATION"], top, false )
+	EMA.settingsControl.areaTypeDropdown = EMAHelperSettings:CreateDropdown(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["MESSAGE_AREA"]
+	)
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	local areaList = {}
+	for areaType, areaTypeInformation in pairs( EMA.areaTypes ) do
+		areaList[areaType] = areaTypeInformation.name
+	end
+	EMA.settingsControl.areaTypeDropdown:SetList( areaList )
+	EMA.settingsControl.areaTypeDropdown:SetCallback( "OnValueChanged", EMA.UpdateAreaTypeControls )
+	EMA.settingsControl.areaEditBoxTag = EMAHelperSettings:CreateEditBox( EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["GROUP"]
+	)
+	EMA.settingsControl.areaEditBoxTag:SetCallback( "OnEnterPressed", EMA.EditBoxTagChanged )
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	EMA.settingsControl.areaEditBoxName = EMAHelperSettings:CreateEditBox( EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["NAME"]
+	)
+	EMA.settingsControl.areaEditBoxName:SetCallback( "OnEnterPressed", EMA.EditBoxNameChanged )
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	EMA.settingsControl.areaEditBoxPassword = EMAHelperSettings:CreateEditBox( EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["PASSWORD"]
+	)
+	EMA.settingsControl.areaEditBoxPassword:SetCallback( "OnEnterPressed", EMA.EditBoxPasswordChanged )
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	EMA.settingsControl.areaOnScreenDropdown = EMAHelperSettings:CreateDropdown(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["AREA"]
+	)
+	EMA.settingsControl.areaOnScreenDropdown:SetCallback( "OnValueChanged", EMA.UpdateAreaOnScreenControls )
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	areaConfigurationTop = areaConfigurationTop - verticalSpacing - verticalSpacing
+	EMA.settingsControl.areaSoundDropdown = EMAHelperSettings:CreateMediaSound(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["SOUND_TO_PLAY"]
+	)
+	EMA.settingsControl.areaSoundDropdown:SetCallback( "OnValueChanged", EMA.UpdateSoundControls )
+
+	areaConfigurationTop = areaConfigurationTop - dropdownHeight
+	areaConfigurationTop = areaConfigurationTop - verticalSpacing - verticalSpacing
+	EMA.settingsControl.areaListButtonUpdate = EMAHelperSettings:CreateButton(
+		EMA.settingsControl,
+		areaListButtonControlWidth,
+		column1Left,
+		areaConfigurationTop,
+		L["SAVE"],
+		EMA.SettingsUpdateClick
+	)
+	areaConfigurationTop = areaConfigurationTop - buttonHeight
+	EMA.settingsControl.areaEditBoxTag:SetDisabled( true )
+	EMA.settingsControl.areaEditBoxTag:SetText( "" )
+	EMA.settingsControl.areaEditBoxName:SetDisabled( true )
+	EMA.settingsControl.areaEditBoxName:SetText( "" )
+	EMA.settingsControl.areaEditBoxPassword:SetDisabled( true )
+	EMA.settingsControl.areaEditBoxPassword:SetText( "" )
+	EMA.settingsControl.areaOnScreenDropdown:SetDisabled( true )
+	EMA.settingsControl.areaOnScreenDropdown:SetText( "" )
+	EMA.settingsControl.areaSoundDropdown:SetDisabled( true )
+	EMA.settingsControl.areaSoundDropdown:SetText( "" )
+	local bottomOfSection = areaConfigurationTop
+	return bottomOfSection
+end
+
+local function SettingsCreate()
+	EMA.settingsControl = {}
+	-- Create the settings panel.
+	EMAHelperSettings:CreateSettings(
+		EMA.settingsControl,
+		EMA.moduleDisplayName,
+		EMA.parentDisplayName,
+		EMA.SettingsPushSettingsClick,
+		EMA.moduleIcon,
+		EMA.moduleOrder
+	)
+	-- Create the area list controls.
+	local bottomOfAreaList = SettingsCreateAreaList()
+	-- Create the area type configuration controls.
+	local bottomOfAreaTypes = SettingsCreateAreaTypes( bottomOfAreaList )
+	EMA.settingsControl.widgetSettings.content:SetHeight( -bottomOfAreaTypes )
+	-- Help
+	local helpTable = {}
+	EMAHelperSettings:CreateHelp( EMA.settingsControl, helpTable, EMA:GetConfiguration() )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Callbacks.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:SettingsAreaListScrollRefresh()
+	FauxScrollFrame_Update(
+		EMA.settingsControl.areaList.listScrollFrame,
+		GetAreaListMaxPosition(),
+		EMA.settingsControl.areaList.rowsToDisplay,
+		EMA.settingsControl.areaList.rowHeight
+	)
+
+	EMA.settingsControl.areaListOffset = FauxScrollFrame_GetOffset( EMA.settingsControl.areaList.listScrollFrame )
+	for iterateDisplayRows = 1, EMA.settingsControl.areaList.rowsToDisplay do
+		-- Reset.
+		EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[1].textString:SetText( "" )
+		EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[2].textString:SetText( "" )
+		EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[2].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.areaList.rows[iterateDisplayRows].highlight:SetColorTexture( 0.0, 0.0, 0.0, 0.0 )
+		-- Get data.
+		local dataRowNumber = iterateDisplayRows + EMA.settingsControl.areaListOffset
+		if dataRowNumber <= GetAreaListMaxPosition() then
+			-- Put area name and type into columns.
+			local areaInformation = GetAreaAtPosition( dataRowNumber )
+			local areaName = areaInformation.name
+			local areaType = EMA.areaTypes[areaInformation.type].name
+			EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[1].textString:SetText( areaName )
+			EMA.settingsControl.areaList.rows[iterateDisplayRows].columns[2].textString:SetText( areaType )
+			-- Highlight the selected row.
+			if dataRowNumber == EMA.settingsControl.areaListHighlightRow then
+				EMA.settingsControl.areaList.rows[iterateDisplayRows].highlight:SetColorTexture( 1.0, 1.0, 0.0, 0.5 )
+			end
+		end
+	end
+end
+
+function EMA:UpdateAreaTypeControls( event, areaTypeIdentifier )
+	EMA.currentlySelectedAreaTypeIdentifier = areaTypeIdentifier
+	local areaType = EMA.areaTypes[areaTypeIdentifier]
+	-- Disable all controls.
+	EMA.settingsControl.areaEditBoxTag:SetDisabled( true )
+	EMA.settingsControl.areaEditBoxName:SetDisabled( true )
+	EMA.settingsControl.areaEditBoxPassword:SetDisabled( true )
+	EMA.settingsControl.areaOnScreenDropdown:SetDisabled( true )
+	EMA.settingsControl.areaSoundDropdown:SetDisabled( true )
+	-- Enable controls if they are used.
+	if areaType.usesTag == true then
+		EMA.settingsControl.areaEditBoxTag:SetDisabled( false )
+	end
+	if areaType.usesChannel == true then
+		EMA.settingsControl.areaEditBoxName:SetDisabled( false )
+		EMA.settingsControl.areaEditBoxPassword:SetDisabled( false )
+	end
+	if areaType.usesChatWindowName == true then
+		EMA.settingsControl.areaEditBoxName:SetDisabled( false )
+	end
+	if areaType.usesScreen == true then
+		-- Nothing here anymore!
+
+	end
+	if areaType.usesSound == true then
+		EMA.settingsControl.areaSoundDropdown:SetDisabled( false )
+	end
+end
+
+local function UpdateAreaTypeInformation()
+	-- Update the area type controls to reflect the information for this selection.
+	local areaInformation = GetAreaAtPosition( EMA.settingsControl.areaListHighlightRow )
+	local areaType = EMA.areaTypes[areaInformation.type]
+	-- Set the area type control.
+	EMA.settingsControl.areaTypeDropdown:SetValue( areaInformation.type )
+	EMA:UpdateAreaTypeControls( "OnValueChanged", areaInformation.type )
+	-- Clear controls.
+	EMA.settingsControl.areaEditBoxTag:SetText( "" )
+	EMA.settingsControl.areaEditBoxName:SetText( "" )
+	EMA.settingsControl.areaEditBoxPassword:SetText( "" )
+	EMA.settingsControl.areaOnScreenDropdown:SetText( "" )
+	-- Populate controls if they are used.
+	if areaType.usesTag == true then
+		EMA.settingsControl.areaEditBoxTag:SetText( areaInformation.tag )
+		EMA.currentEditBoxTagText = areaInformation.tag
+	end
+	if areaType.usesChannel == true then
+		EMA.settingsControl.areaEditBoxName:SetText( areaInformation.channelName )
+		EMA.currentEditBoxNameText = areaInformation.channelName
+		EMA.settingsControl.areaEditBoxPassword:SetText( areaInformation.channelPassword )
+		EMA.currentEditBoxPasswordText = areaInformation.channelPassword
+	end
+	if areaType.usesChatWindowName == true then
+		EMA.settingsControl.areaEditBoxName:SetText( areaInformation.chatWindowName )
+		EMA.currentEditBoxNameText = areaInformation.chatWindowName
+	end
+	if areaType.usesScreen == true then
+		EMA.settingsControl.areaOnScreenDropdown:SetValue( areaInformation.areaOnScreenName )
+		EMA:UpdateAreaOnScreenControls( "OnValueChanged", areaInformation.areaOnScreenName )
+	end
+	if areaType.usesSound == true then
+		EMA.settingsControl.areaSoundDropdown:SetValue( areaInformation.soundToPlay )
+	end
+end
+
+function EMA:SettingsAreaListRowClick( rowNumber, columnNumber )
+	if EMA.settingsControl.areaListOffset + rowNumber <= GetAreaListMaxPosition() then
+		EMA.settingsControl.areaListHighlightRow = EMA.settingsControl.areaListOffset + rowNumber
+		UpdateAreaTypeInformation()
+		EMA:SettingsAreaListScrollRefresh()
+	end
+end
+
+function EMA:EditBoxTagChanged( event, text )
+	EMA.currentEditBoxTagText = text
+end
+
+function EMA:EditBoxNameChanged( event, text )
+	EMA.currentEditBoxNameText = text
+end
+
+function EMA:EditBoxPasswordChanged( event, text )
+	EMA.currentEditBoxPasswordText = text
+end
+
+local function SetAreaConfigurationIntoCurrentArea()
+	-- Get information from table at position.
+	local areaInformation = GetAreaAtPosition( EMA.settingsControl.areaListHighlightRow )
+	-- Update the area type for this area.
+	areaInformation.type = EMA.currentlySelectedAreaTypeIdentifier
+	-- Get the area information.
+	local areaType = EMA.areaTypes[areaInformation.type]
+	-- Update the area information according to the area type.
+	if areaType.usesTag == true then
+		areaInformation.tag = EMA.currentEditBoxTagText
+	end
+	if areaType.usesChannel == true then
+		areaInformation.channelName = EMA.currentEditBoxNameText
+		areaInformation.channelPassword = EMA.currentEditBoxPasswordText
+	end
+	if areaType.usesChatWindowName == true then
+		areaInformation.chatWindowName = EMA.currentEditBoxNameText
+	end
+	if areaType.usesScreen == true then
+		areaInformation.areaOnScreenName = EMA.currentlySelectedAreaOnScreenName
+	end
+	if areaType.usesSound == true then
+		areaInformation.soundToPlay = EMA.currentlySelectedAreaSoundToPlay
+	end
+	-- Put information back into table at position.
+	SetAreaAtPosition( EMA.settingsControl.areaListHighlightRow, areaInformation )
+	-- Refresh the settings.
+	EMA:SettingsRefresh()
+end
+
+function EMA:UpdateAreaOnScreenControls( event, areaOnScreenName )
+	EMA.currentlySelectedAreaOnScreenName = areaOnScreenName
+end
+
+function EMA:UpdateSoundControls( event, value )
+	EMA.settingsControl.areaSoundDropdown:SetValue( value )
+	EMA.currentlySelectedAreaSoundToPlay = value
+end
+
+function EMA:SettingsPushSettingsClick( event )
+	EMA:EMASendSettings()
+	--EMA:SendMessage( EMA.MESSAGE_MESSAGE_AREAS_CHANGED )
+end
+
+function EMA:SettingsUpdateClick( event )
+	SetAreaConfigurationIntoCurrentArea()
+end
+
+function EMA:SettingsAddClick( event )
+	StaticPopup_Show( "EMAMESSAGE_ASK_AREA_NAME" )
+end
+
+function EMA:SettingsRemoveClick( event )
+	local area = GetAreaAtPosition( EMA.settingsControl.areaListHighlightRow )
+	StaticPopup_Show( "EMAMESSAGE_CONFIRM_REMOVE_AREA", area.name )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Popup Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialize Popup Dialogs.
+local function InitializePopupDialogs()
+   StaticPopupDialogs["EMAMESSAGE_ASK_AREA_NAME"] = {
+        text = L["STATICPOPUP_ADD_MSG"],
+        button1 = ACCEPT,
+        button2 = CANCEL,
+        hasEditBox = 1,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+		OnShow = function( self )
+			self.editBox:SetText("")
+            self.button1:Disable()
+            self.editBox:SetFocus()
+        end,
+        OnAccept = function( self )
+			EMA:AddAreaGUI( self.editBox:GetText() )
+		end,
+        EditBoxOnTextChanged = function( self )
+            if not self:GetText() or self:GetText():trim() == "" then
+				self:GetParent().button1:Disable()
+            else
+                self:GetParent().button1:Enable()
+            end
+        end,
+		EditBoxOnEnterPressed = function( self )
+            if self:GetParent().button1:IsEnabled() then
+				EMA:AddAreaGUI( self:GetText() )
+            end
+            self:GetParent():Hide()
+        end,
+    }
+   StaticPopupDialogs["EMAMESSAGE_CONFIRM_REMOVE_AREA"] = {
+        text = L["REMOVE_MESSAGE_AREA"],
+        button1 = YES,
+        button2 = NO,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+        OnAccept = function( self )
+			EMA:RemoveAreaGUI()
+		end,
+    }
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Addon initialization, enabling and disabling.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialise the module.
+function EMA:OnInitialize()
+	EMA.currentlySelectedAreaTypeIdentifier = EMA.AREA_TYPE_DEFAULT_CHAT
+	EMA.currentEditBoxTagText = ""
+	EMA.currentEditBoxNameText = ""
+	EMA.currentEditBoxPasswordText = ""
+	EMA.currentlySelectedAreaOnScreenName = ""
+	EMA.currentlySelectedAreaSoundToPlay = ""
+	-- Create the settings control.
+	SettingsCreate()
+	-- Initialise the EMAModule part of this module.
+	EMA:EMAModuleInitialize( EMA.settingsControl.widgetSettings.frame )
+	-- Populate the settings.
+	EMA:SettingsRefresh()
+	-- Initialise the popup dialogs.
+	InitializePopupDialogs()
+	-- Click the area list first row, column to set the child controls.
+	EMA:SettingsAreaListRowClick( 1, 1 )
+end
+
+-- Called when the addon is enabled.
+function EMA:OnEnable()
+	-- Kickstart the settings team list scroll frame.
+	EMA:SettingsAreaListScrollRefresh()
+end
+
+-- Called when the addon is disabled.
+function EMA:OnDisable()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Send messages.
+-------------------------------------------------------------------------------------------------------------
+
+local function DefaultMessageArea()
+	return L["DEFAULT_MESSAGE"]
+end
+
+local function DefaultWarningArea()
+	return L["DEFAULT_WARNING"]
+end
+
+local function DisplayMessageDefaultChat( sender, message, suppressSender )
+	local senderName = Ambiguate(sender, "none")
+	local chatTimestamp = ""
+	if (CHAT_TIMESTAMP_FORMAT) then
+		chatTimestamp = BetterDate( CHAT_TIMESTAMP_FORMAT, time() )
+	end
+	local completeMessage = chatTimestamp
+	if suppressSender == false then
+		completeMessage = completeMessage.."|Hplayer:"..sender.."|h["..senderName.."]|h"..L[": "]
+	end
+	completeMessage = completeMessage..message
+	DEFAULT_CHAT_FRAME:AddMessage( completeMessage )
+end
+
+local function DisplayMessageChatWhisper( sender, message, suppressSender )
+	-- The whisper comes across the wire and you whisper yourself...
+	-- If we clean up EMA-msg then we can remove this maybe again Eboyn TODO::::
+	EMAPrivate.Communications.SendChatMessage( message, "WHISPER", sender, EMAPrivate.Communications.COMMUNICATION_PRIORITY_ALERT )
+end
+
+local function DisplayMessageChat( sender, message, chatDestination, suppressSender )
+	local canSend = false
+	if (chatDestination == "GUILD" or chatDestination == "OFFICER") then
+		if IsInGuild() then
+			canSend = true
+		else
+			EMA:Print( L["ERROR: Not in a Guild"] )
+		end
+	end
+	if chatDestination == "PARTY" then
+		if GetNumSubgroupMembers() > 0 then
+			canSend = true
+		else
+			EMA:Print( L["ERROR: Not in a Party"] )
+		end
+	end
+	if chatDestination == "RAID" then
+		if GetNumGroupMembers() > 0 and IsInRaid() then
+			canSend = true
+		else
+			EMA:Print( L["ERROR: Not in a Raid"] )
+		end
+	end
+	if canSend == true then
+		-- If we clean up EMA-msg then we can remove this maybe again Eboyn TODO::::
+		EMAPrivate.Communications.SendChatMessage( message, chatDestination, nil, EMAPrivate.Communications.COMMUNICATION_PRIORITY_ALERT )
+	else
+		EMA:Print( message )
+	end
+end
+
+local function DisplayMessageRaidWarning( sender, message, suppressSender )
+	local completeMessage = ""
+	local senderName = Ambiguate(sender, "none")
+	if suppressSender == false then
+		completeMessage = completeMessage..senderName..L[": "]
+	end
+	completeMessage = completeMessage..message
+	RaidNotice_AddMessage( RaidWarningFrame, completeMessage, ChatTypeInfo["RAID_WARNING"] )
+end
+
+
+local function PlayMessageSound( soundToPlay )
+	PlaySoundFile( Media:Fetch( 'sound', soundToPlay ), "Ambience" )
+end
+
+local function ProcessReceivedMessage( sender, areaName, message, suppressSender, ... )
+	-- Get the area requested.
+	local area = GetAreaByName( areaName )
+	if area == nil then
+		EMA:Print( L["ERROR: Could not find area: A"]( areaName ) )
+		EMA:Print( message )
+		return
+	end
+	-- What sort of area is this?
+	local areaType = EMA.areaTypes[area.type]
+	-- Does this area type use tags?  If so, check the tag.
+	if areaType.usesTag == true then
+		if EMAPrivate.Tag.DoesCharacterHaveTag( EMA.characterName, area.tag ) == false then
+			-- Tag not on this character, bail.
+			return
+		end
+	end
+	-- Display the message.
+	if area.type == EMA.AREA_TYPE_DEFAULT_CHAT then
+		DisplayMessageDefaultChat( sender, message, suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_SPECIFIC_CHAT then
+		-- TODO
+	end
+	if area.type == EMA.AREA_TYPE_WHISPER then
+		DisplayMessageChatWhisper( sender, message, suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_PARTY then
+		DisplayMessageChat( sender, message, "PARTY", suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_GUILD then
+		DisplayMessageChat( sender, message, "GUILD", suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_GUILD_OFFICER then
+		DisplayMessageChat( sender, message, "OFFICER", suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_RAID then
+		DisplayMessageChat( sender, message, "RAID", suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_RAID_WARNING then
+		DisplayMessageRaidWarning( sender, message, suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_CHANNEL then
+		-- TODO
+	end
+--[[
+	if area.type == EMA.AREA_TYPE_PARROT then
+		DisplayMessageParrot( sender, message, area.areaOnScreenName, suppressSender )
+	end
+	if area.type == EMA.AREA_TYPE_MSBT then
+		DisplayMessageMikSBT( sender, message, area.areaOnScreenName, suppressSender )
+	end
+]]
+	if area.type == EMA.AREA_TYPE_MUTE then
+		-- Do nothing! Mute means eat the message.
+	end
+	if areaType.usesSound == true and area.soundToPlay ~= "None" then
+		PlayMessageSound(area.soundToPlay)
+	end
+end
+
+local function SendMessage( areaName, message, suppressSender, ... )
+	-- Get the area requested.
+	local area = GetAreaByName( areaName )
+	if area == nil then
+		EMA:Print( L["ERR_COULD_NOT_FIND_AREA"]( areaName ) )
+
+		EMA:Print( message )
+		return
+	end
+	-- What sort of area is this?
+	local areaType = EMA.areaTypes[area.type]
+	-- Does this area type use tags?  If so, find out if the message needs to be sent over the wire.
+	local sendToJustMe = false
+	if areaType.usesTag == true then
+		--if area.tag == EMAPrivate.Tag.JustMeTag() then
+		--	sendToJustMe = true
+		--end
+		if area.tag == EMAPrivate.Tag.MasterTag() and EMAPrivate.Team.IsCharacterTheMaster( EMA.characterName ) == true then
+			sendToJustMe = true
+		end
+	end
+	-- Send over the wire or process locally?
+	if sendToJustMe == true or areaType.mustBeWired == false then
+		ProcessReceivedMessage( EMA.characterName, areaName, message, suppressSender, ... )
+	else
+		EMA:EMASendCommandToTeam( EMA.COMMAND_MESSAGE, areaName, message, suppressSender, ... )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Commands.
+-------------------------------------------------------------------------------------------------------------
+
+-- A EMA command has been recieved.
+function EMA:EMAOnCommandReceived( characterName, commandName, ... )
+	if commandName == EMA.COMMAND_MESSAGE then
+		ProcessReceivedMessage( characterName, ... )
+	end
+end
+
+-- Functions available from EMA Message for other EMA internal objects.
+EMAPrivate.Message.SendMessage = SendMessage
+
+-- Functions available for other addons.
+EMAApi.MessageAreaList = MessageAreaList
+EMAApi.DefaultMessageArea = DefaultMessageArea
+EMAApi.DefaultWarningArea = DefaultWarningArea
+EMAApi.MESSAGE_MESSAGE_AREAS_CHANGED = EMA.MESSAGE_MESSAGE_AREAS_CHANGED
diff --git a/Core/Module-Classic.lua b/Core/Module-Classic.lua
new file mode 100644
index 0000000..54dfb70
--- /dev/null
+++ b/Core/Module-Classic.lua
@@ -0,0 +1,189 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+local MAJOR, MINOR = "Module-1.0", 2
+local EMAModule, oldMinor = LibStub:NewLibrary( MAJOR, MINOR )
+
+if not EMAModule then
+	return
+end
+
+-- Load libraries.
+LibStub( "AceConsole-3.0" ):Embed( EMAModule )
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Module Mixin Management.
+-------------------------------------------------------------------------------------------------------------
+
+-- A list of modules that embed this module.
+EMAModule.embeddedModules = EMAModule.embeddedModules or {}
+
+-- These methods are the embbedable methods.
+
+local mixinMethods = {
+	"EMARegisterModule", "EMAModuleInitialize",
+	"EMASendCommandToTeam", "EMASendCommandToMaster",
+	"EMASendMessageToTeam", "EMASendCommandToToon",
+	"EMASendSettings", "EMAOnSettingsReceived",
+	"EMAChatCommand",
+	"EMAConfigurationGetSetting", "EMAConfigurationSetSetting",
+}
+
+-- Embed all the embeddable methods into the target module.
+function EMAModule:Embed( targetModule )
+	for key, value in pairs( mixinMethods ) do
+		targetModule[value] = self[value]
+	end
+	LibStub( "AceConsole-3.0" ):Embed( targetModule )
+	self.embeddedModules[targetModule] = true
+	return targetModule
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Module Registration.
+-------------------------------------------------------------------------------------------------------------
+
+-- Register a module with EMA.  EMA needs modules to be registered in order to faciliate communications.
+function EMAModule:EMARegisterModule( moduleName )
+	EMAPrivate.Core.RegisterModule( self, moduleName )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Communications.
+-------------------------------------------------------------------------------------------------------------
+
+-- Send settings to all available EMA Team characters.
+function EMAModule:EMASendSettings()
+	EMAPrivate.Core.SendSettings( self, self.db )
+end
+
+-- Send a command to all available EMA Team characters.
+function EMAModule:EMASendCommandToTeam( commandName, ... )
+	EMAPrivate.Core.SendCommandToTeam( self, commandName, ... )
+end
+
+-- Send a command to just the master character.
+function EMAModule:EMASendCommandToMaster( commandName, ... )
+	EMAPrivate.Core.SendCommandToMaster( self, commandName, ... )
+end
+
+function EMAModule:EMASendCommandToToon( characterName, commandName, ... )
+	EMAPrivate.Core.SendCommandToToon( self, characterName, commandName, ... )
+end
+
+-- Send a message to the team.
+function EMAModule:EMASendMessageToTeam( areaName, message, suppressSender, ... )
+	EMAPrivate.Message.SendMessage( areaName, message, suppressSender, ... )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- EMA Chat Commands.
+-------------------------------------------------------------------------------------------------------------
+-- Does the Chat Command Exist
+local function DoesTheChatCommandExist( configuration, command )
+	local exist = false
+	for key, info in pairs( configuration ) do
+		stringName = string.lower( key )
+		--print("aa", stringName, "vs", command )
+		if info.type == "input" then
+			if stringName == command then
+				exist = true
+				break
+			end
+		end
+	end
+	return exist
+end
+
+-- Handle the chat command v2 EMA.
+function EMAModule:EMAChatCommand( inputBefore )
+	input = string.lower( inputBefore )
+	--print("test2", "input", input, "command", self.chatCommand, "module", self.moduleName )
+	local inputString, tag = strsplit( " ", inputBefore )
+	local CommandExist = DoesTheChatCommandExist( self:GetConfiguration().args, inputString )
+	if input == "config" then
+		if InCombatLockdown() then
+			print( L["CANNOT_OPEN_IN_COMBAT"] )
+		return
+	end
+		-- Show Config
+		EMAPrivate.SettingsFrame.Widget:Show()
+		EMAPrivate.SettingsFrame.TreeGroupStatus.groups[self.parentDisplayName] = true
+		EMAPrivate.SettingsFrame.WidgetTree:SelectByPath( self.parentDisplayName, self.moduleDisplayName )
+		EMAPrivate.SettingsFrame.Tree.ButtonClick( nil, nil, self.moduleDisplayName, false)
+	elseif CommandExist then
+		--Command Found now Handle IT!
+		--print("Command Found", input )
+		LibStub( "AceConfigCmd-3.0" ):HandleCommand( self.chatCommand, self.moduleName, input )
+	else
+		-- hell knows what to do so HELP!!!
+		--print("No found Command Found HELP", input )
+		for key, info in pairs( self:GetConfiguration().args ) do
+			if info.type == "input" then
+				print("|cFFFFFF00"..info.usage, "|cFFFFFFFF".." [ "..info.desc.." ]" )
+			end
+		end
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Module initialization and settings management.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialise the module.
+function EMAModule:EMAModuleInitialize( settingsFrame )
+    -- Create the settings database supplying the settings values along with defaults.
+	self.completeDatabase = LibStub( "AceDB-3.0" ):New( self.settingsDatabaseName, self.settings )
+	self.db = self.completeDatabase.profile
+	self.db.global = self.completeDatabase.global
+	-- Create the settings.
+	LibStub( "AceConfig-3.0" ):RegisterOptionsTable( self.moduleName, self:GetConfiguration() )
+	self.settingsFrame = settingsFrame
+	-- Register the chat command for this module.
+	--print("EMAChatCommand", self.chatCommand, self.chatCommandTwo, self.chatCommandThree )
+	if self.chatCommand then
+		self:RegisterChatCommand( self.chatCommand, "EMAChatCommand" )
+	end
+	-- Remember the characters name.
+	-- If server has a space in realm name GetRealmName() will show space this will not work with blizzard API so we need to hack this to work --ebony
+	--local _, k = UnitFullName("player")
+	local k = GetRealmName()
+	local realm = k:gsub( "%s+", "")
+	self.characterRealm = realm
+	self.characterNameLessRealm = UnitName( "player" )
+	--self.characterName = UnitFullName( "player" )
+	self.characterName = self.characterNameLessRealm.."-"..self.characterRealm
+	--self.characterName = UnitFullName("player")
+	self.characterGUID = UnitGUID( "player" )
+	-- Register this module with EMA.
+	self:EMARegisterModule( self.moduleName )
+end
+
+-- Get a settings value.
+function EMAModule:EMAConfigurationGetSetting( key )
+	return self.db[key[#key]]
+end
+
+-- Set a settings value.
+function EMAModule:EMAConfigurationSetSetting( key, value )
+	self.db[key[#key]] = value
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Upgrade Library.
+-------------------------------------------------------------------------------------------------------------
+
+-- Upgrade all modules that are already using this library to use the newer version.
+for targetModule, value in pairs( EMAModule.embeddedModules ) do
+	EMAModule:Embed( targetModule )
+end
diff --git a/Core/Tag-Classic.lua b/Core/Tag-Classic.lua
new file mode 100644
index 0000000..940fff5
--- /dev/null
+++ b/Core/Tag-Classic.lua
@@ -0,0 +1,775 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+-- Create the addon using AceAddon-3.0 and embed some libraries.
+local EMA = LibStub( "AceAddon-3.0" ):NewAddon(
+	"Tag",
+	"Module-1.0",
+	"AceConsole-3.0",
+	"AceEvent-3.0",
+	"AceHook-3.0"
+)
+
+-- Load libraries.
+local EMAUtilities = LibStub:GetLibrary( "EbonyUtilities-1.0" )
+local EMAHelperSettings = LibStub:GetLibrary( "EMAHelperSettings-1.0" )
+local AceGUI = LibStub( "AceGUI-3.0" )
+
+-- Constants required by EMAModule and Locale for this module.
+EMA.moduleName = "Tag"
+EMA.settingsDatabaseName = "TagProfileDB"
+EMA.chatCommand = "ema-group"
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+EMA.parentDisplayName = L["TEAM"]
+EMA.moduleDisplayName = L["GROUP_LIST"]
+-- Icon
+EMA.moduleIcon = "Interface\\Addons\\EMA-Classic\\Media\\GroupIcon.tga"
+-- order
+EMA.moduleOrder = 10
+
+-- Settings - the values to store and their defaults for the settings database.
+EMA.settings = {
+	profile = {
+        tagList = {},
+		groupList = {}
+	},
+}
+
+-- Configuration.
+function EMA:GetConfiguration()
+	local configuration = {
+		name = EMA.moduleDisplayName,
+		handler = EMA,
+		type = "group",
+		get = "EMAConfigurationGetSetting",
+		set = "EMAConfigurationSetSetting",
+		args = {
+			config = {
+				type = "input",
+				name = L["OPEN_CONFIG"],
+				desc = L["OPEN_CONFIG_HELP"],
+				usage = "/ema-group confg",
+				get = false,
+				set = "",
+			},
+			add = {
+				type = "input",
+				name = L["ADD"],
+				desc = L["ADD_TAG_HELP"],
+				usage = "/ema-group add <NewGroupName>",
+				get = false,
+				set = "AddTagCommand",
+			},
+			remove = {
+				type = "input",
+				name = L["REMOVE"],
+				desc = L["REMMOVE_TAG_HELP"],
+				usage = "/ema-group remove <NewGroupName>",
+				get = false,
+				set = "RemoveTagCommand",
+			},
+			addtogroup = {
+				type = "input",
+				name = L["ADD_TO_GROUP"],
+				desc = L["ADD_TO_GROUP_HELP"],
+				usage = "/ema-group addtogroup <characterName> <GroupName>",
+				get = false,
+				set = "AddToGroupCommand",
+			},
+			removefromgroup = {
+				type = "input",
+				name = L["REMOVE_FROM_GROUP"],
+				desc = L["REMOVE_FROM_GROUP_HELP"],
+				usage = "/ema-group removefromgroup <characterName> <NewGroupName>",
+				get = false,
+				set = "RemovefromGroupCommand",
+			},
+			push = {
+				type = "input",
+				name = L["PUSH_ALL_SETTINGS"],
+				desc = L["PUSH_SETTINGS_INFO"],
+				usage = "/ema-group push",
+				get = false,
+				set = "EMASendSettings",
+			},
+		},
+	}
+	return configuration
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Command this module sends.
+-------------------------------------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------------------------------------
+-- Messages module sends.
+-------------------------------------------------------------------------------------------------------------
+EMA.GROUP_LIST_CHANGED = "EMAMessageGroupListChanged"
+-------------------------------------------------------------------------------------------------------------
+-- Constants used by module.
+-------------------------------------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+local function SettingsCreateGroupList()
+	-- Position and size constants.
+	local top = EMAHelperSettings:TopOfSettings()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local iconSize = 30
+	local iconHight = iconSize + 10
+	local lefticon =  left + iconSize
+	local teamListWidth = headingWidth - 90
+	local topOfList = top - headingHeight
+	-- Team list internal variables (do not change).
+	EMA.settingsControl.teamListHighlightRow = 1
+	EMA.settingsControl.teamListOffset = 1
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	topOfList = topOfList - headingHeight
+	--Main Heading
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["GROUP_LIST"], top, false )
+	-- Create a team list frame.
+
+	local list = {}
+	list.listFrameName = "EMATagSettingsGroupListFrame"
+	list.parentFrame = EMA.settingsControl.widgetSettings.content
+	list.listTop = topOfList
+	list.listLeft = lefticon
+	list.listWidth = teamListWidth
+	list.rowHeight = 20
+	list.rowsToDisplay = 15
+	list.columnsToDisplay = 1
+	list.columnInformation = {}
+	list.columnInformation[1] = {}
+	list.columnInformation[1].width = 100
+	list.columnInformation[1].alignment = "LEFT"
+	list.scrollRefreshCallback = EMA.SettingsGroupListScrollRefresh
+	list.rowClickCallback = EMA.SettingsGroupListRowClick
+	EMA.settingsControl.groupList = list
+	EMAHelperSettings:CreateScrollList( EMA.settingsControl.groupList )
+	-- Position and size constants (once list height is known).
+	local bottomOfList = topOfList - list.listHeight - verticalSpacing
+
+	EMA.settingsControl.tagListButtonAdd = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharAddParty.tga", --icon Image
+		left - iconSize - 11,
+		topOfList - verticalSpacing ,
+		L[""],
+		EMA.SettingsAddClick,
+		L["BUTTON_TAG_ADD_HELP"]
+	)
+	EMA.settingsControl.groupListButtonRemove = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharRemoveParty.tga", --icon Image
+		left - iconSize - 11,
+		topOfList - verticalSpacing - iconHight,
+		L[""],
+		EMA.SettingsRemoveClick,
+		L["BUTTON_TAG_REMOVE_HELP"]
+	)
+	local bottomOfSection = bottomOfList -  buttonHeight - verticalSpacing
+
+	return bottomOfSection
+end
+
+local function SettingsCreate()
+	EMA.settingsControl = {}
+	-- Create the settings panel.
+	EMAHelperSettings:CreateSettings(
+		EMA.settingsControl,
+		EMA.moduleDisplayName,
+		EMA.parentDisplayName,
+		EMA.SettingsPushSettingsClick,
+		EMA.moduleIcon,
+		EMA.moduleOrder
+	)
+	-- Create the team list controls.
+	local bottomOfGroupList = SettingsCreateGroupList()
+	local helpTable = {}
+	EMAHelperSettings:CreateHelp( EMA.settingsControl, helpTable, EMA:GetConfiguration() )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Populate.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:BeforeEMAProfileChanged()
+end
+
+function EMA:OnEMAProfileChanged()
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsRefresh()
+	-- Update the settings team list.
+	EMA:SettingsGroupListScrollRefresh()
+	--EMA:SettingsTagListScrollRefresh()
+end
+
+-- Settings received.
+function EMA:EMAOnSettingsReceived( characterName, settings )
+	characterName = EMAUtilities:AddRealmToNameIfMissing( characterName )
+	if characterName ~= EMA.characterName then
+		-- Update the settings.
+		EMA.db.tagList = EMAUtilities:CopyTable( settings.tagList )
+		EMA.db.groupList = EMAUtilities:CopyTable( settings.groupList )
+		EMA:InitializeAllTagsList()
+		-- New team and tag lists coming up, highlight first item in each list.
+		EMA.settingsControl.groupListHighlightRow = 1
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		EMA:SettingsGroupListRowClick( 1, 1 )
+		EMA:SendMessage( EMA.GROUP_LIST_CHANGED )
+		EMAApi.refreshDropDownList()
+		-- Tell the player.
+		EMA:Print( L["SETTINGS_RECEIVED_FROM_A"]( characterName ) )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Popup Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialize Popup Dialogs.
+local function InitializePopupDialogs()
+   -- Ask the name of the tag to add as to the character.
+   StaticPopupDialogs["EMATAG_ASK_TAG_NAME"] = {
+        text = L["NEW_GROUP_NAME"],
+        button1 = ACCEPT,
+        button2 = CANCEL,
+        hasEditBox = 1,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+		OnShow = function( self )
+			self.editBox:SetText("")
+            self.button1:Disable()
+            self.editBox:SetFocus()
+        end,
+		OnAccept = function( self )
+			EMA:AddTagGUI( self.editBox:GetText() )
+		end,
+		EditBoxOnTextChanged = function( self )
+            if not self:GetText() or self:GetText():trim() == "" then
+				self:GetParent().button1:Disable()
+            else
+                self:GetParent().button1:Enable()
+            end
+        end,
+		EditBoxOnEnterPressed = function( self )
+            if self:GetParent().button1:IsEnabled() then
+				EMA:AddTagGUI( self:GetText() )
+            end
+            self:GetParent():Hide()
+        end,
+    }
+   -- Confirm removing characters from member list.
+   StaticPopupDialogs["EMATAG_CONFIRM_REMOVE_TAG"] = {
+        text = L["REMOVE_FROM_TAG_LIST"],
+		button1 = ACCEPT,
+        button2 = CANCEL,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+        OnAccept = function( self )
+			EMA:RemoveTagGUI()
+		end,
+    }
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Group Management.
+-------------------------------------------------------------------------------------------------------------
+
+local function AllTag()
+	return L["ALL_LOWER"]
+end
+
+local function MasterTag()
+	return L["MASTER_LOWER"]
+end
+
+local function MinionTag()
+	return L["MINION_LOWER"]
+end
+
+local function GroupList()
+	return EMA.db.groupList
+end
+
+-- Does the Group list have this tag?
+local function DoesGroupExist( group )
+	local tag = EMAUtilities:Lowercase(group)
+	local haveTag = false
+	for index, findTag in ipairs( EMA.db.groupList ) do
+		--EMA:Print("find", findTag, index )
+		if findTag == tag then
+			haveTag = true
+			break
+		end
+	end
+	return haveTag
+end
+
+local function AddGroup( group )
+	if group ~= nil then
+		if DoesGroupExist( group ) == false then
+			table.insert( EMA.db.groupList, group )
+			table.sort( EMA.db.groupList )
+			EMAApi.refreshDropDownList()
+			EMA:SendMessage( EMA.GROUP_LIST_CHANGED )
+		end
+	end
+end
+
+-- If Calling to Remove a group we should Use EMAApi.RemoveGroup( Groupname ) or RemoveGroup then using This
+local function RemoveFromGroupList( tag )
+	if DoesGroupExist( tag ) == true then
+		for index, group in pairs( EMA.db.groupList ) do
+			if group == tag then
+			table.remove( EMA.db.groupList, index )
+			table.sort( EMA.db.groupList )
+			end
+		end
+	EMA:SettingsGroupListScrollRefresh()
+	EMAApi.refreshDropDownList()
+	EMA:SendMessage( EMA.GROUP_LIST_CHANGED )
+	end
+end
+
+local function RemoveGroup( tag )
+	--  We don't Want to Tag to be part of the character Groups as it has been removed!
+	for characterName, tagList in pairs( EMA.db.tagList ) do
+		for index, tagIterated in ipairs( tagList ) do
+			if tagIterated == tag then
+				--EMA:Print("Remove tag:", tag, "from character:", characterName )
+				EMAApi.RemoveGroupFromCharacter( characterName, tag )
+			end
+		end
+	end
+	RemoveFromGroupList( tag )
+	EMA:SettingsGroupListScrollRefresh()
+	EMAPrivate.Team.RefreshGroupList()
+	EMA:SettingsGroupListRowClick( EMA.settingsControl.groupListHighlightRow - 1, 1 )
+	EMA:SendMessage( EMA.GROUP_LIST_CHANGED )
+end
+
+-- We Do Not Want To Remove "System" Groups!
+local function IsASystemGroup( tag )
+	if tag == MasterTag() or tag == MinionTag() or tag == AllTag() then
+		return true
+	end
+	--[[
+	for id, apiClass in pairs( CLASS_SORT_ORDER ) do
+		if tag == EMAUtilities:Lowercase(apiClass) then
+			return true
+		end
+	end
+	]]
+	return false
+end
+
+local function GetGroupListMaximumOrder()
+	local largestPosition = 0
+	for groupId, tag in pairs( EMA.db.groupList ) do
+		if groupId > largestPosition then
+			largestPosition = groupId
+		end
+	end
+	return largestPosition
+end
+
+local function GetGroupAtPosition( position )
+	--EMA:Print("test", position )
+	groupAtPosition = nil
+		for groupId, groupName in pairs( EMA.db.groupList ) do
+			if groupId == position then
+				--EMA:Print("cptest",characterName, groupId, groupName)
+				groupAtPosition = groupName
+			end
+		end
+	return groupAtPosition
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Team Group Management.
+-------------------------------------------------------------------------------------------------------------
+
+local function TeamGroupList()
+	return EMA.db.groupList
+end
+
+local function IsCharacterInGroup( characterName, group )
+	local tag = EMAUtilities:Lowercase(group)
+	local DoesCharacterHaveTag = false
+	for name, tagList in pairs( EMA.db.tagList ) do
+		if characterName == name then
+			for index, tagIterated in pairs( tagList ) do
+				if tag == tagIterated then
+					DoesCharacterHaveTag = true
+				end
+			end
+		end
+	end
+	return DoesCharacterHaveTag
+end
+
+local function GetGroupListForCharacter( characterName )
+	--EMA:Print("getList", characterName)
+	characterName = EMAUtilities:AddRealmToNameIfMissing( characterName )
+	if EMA.db.tagList[characterName] ~= nil then
+		return EMA.db.tagList[characterName]
+	end
+end
+
+local function CharacterMaxGroups()
+	--return EMA.characterTagList
+	local maxOrder = 0
+	for characterName, tagList in pairs( EMA.db.tagList ) do
+		for index, tag in pairs( tagList ) do
+			if index >= maxOrder then
+				maxOrder = index
+			end
+		end
+	end
+	return maxOrder
+end
+
+local function DisplayGroupsForCharacter( characterName )
+	EMA.characterTagList = GetGroupListForCharacter( characterName )
+	table.sort( EMA.characterTagList )
+	EMA:SettingsGroupListScrollRefresh()
+end
+
+local function CharacterAlreadyInGroup( characterName, tag )
+	local canAdd = false
+	return canAdd
+end
+
+local function AddCharacterToGroup( characterName, tag )
+	if characterName == nil or tag == nil then
+		return
+	end
+	-- We Add The GroupName To The characterName in the list!
+	for name, tagList in pairs( EMA.db.tagList ) do
+		if characterName == name then
+			local allReadyInGroup = IsCharacterInGroup( characterName, tag )
+			--EMA:Print("hereWeAddTOTagList", characterName, tag, allReadyInGroup)
+			if allReadyInGroup == false then
+				table.insert(  tagList, tag )
+				table.sort ( tagList )
+				EMAPrivate.Team.RefreshGroupList()
+			end
+		end
+	end
+end
+
+local function RemoveGroupFromCharacter( characterName, tag )
+	if characterName == nil or tag == nil then
+		return
+	end
+	-- We Remove a GroupName From the characterName in the list!
+	for name, tagList in pairs( EMA.db.tagList ) do
+		if characterName == name then
+			for index, tagIterated in pairs( tagList ) do
+				if tag == tagIterated then
+					--EMA:Print("timetoRemovetag")
+					table.remove( tagList, index )
+					table.sort( tagList )
+				end
+			end
+		end
+	end
+end
+
+-- This should abeble to be removed now.
+-- this can be used to add a character that you already know the name of the table. [characterTable] [GroupName/Tag]
+local function AddTag( tagList, tag )
+	table.insert( tagList, tag )
+	AddGroup( tag )
+	EMA:SettingsGroupListScrollRefresh()
+	EMAPrivate.Team.RefreshGroupList()
+end
+
+--TODO ADD CLASS TO LIST
+local function CheckSystemTagsAreCorrect()
+	for characterName, characterPosition in EMAPrivate.Team.TeamList() do
+		--EMA:Print("CHeckTags", characterName)
+		local characterTagList = GetGroupListForCharacter( characterName )
+		-- Do we have a tagList for this character? if not make one!
+		if characterTagList == nil then
+			EMA.db.tagList[characterName] = {}
+		end
+		-- Make sure all characters have the "all" tag.
+		if IsCharacterInGroup ( characterName, AllTag() ) == false then
+			AddCharacterToGroup( characterName, AllTag() )
+		end
+		-- Find Class and add If Known.
+		-- TODO ADD HERE
+
+
+		-- Master or minion?
+		if EMAPrivate.Team.IsCharacterTheMaster( characterName ) == true then
+			--EMA:Print("Master", characterName, characterTagList)
+			if IsCharacterInGroup ( characterName, MasterTag() ) == false then
+				AddCharacterToGroup( characterName, MasterTag() )
+			end
+			if IsCharacterInGroup ( characterName, MinionTag() ) == true then
+				RemoveGroupFromCharacter( characterName, MinionTag() )
+			end
+		else
+			-- Make sure minions have the minion tag and not the master tag.
+			if IsCharacterInGroup ( characterName, MasterTag() ) == true then
+				RemoveGroupFromCharacter( characterName, MasterTag() )
+			end
+			if IsCharacterInGroup ( characterName, MinionTag() ) == false then
+				AddCharacterToGroup( characterName, MinionTag() )
+			end
+		end
+	end
+end
+
+-- Initialise the The Group list.
+function EMA:InitializeAllTagsList()
+	-- Add system tags to the list.
+	AddGroup( AllTag() )
+	AddGroup( MasterTag() )
+	AddGroup( MinionTag() )
+	for id, class in pairs( CLASS_SORT_ORDER ) do
+		AddGroup( EMAUtilities:Lowercase(class) )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- GUI & Command Lines & Other Addons Acess.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:AddTagGUI( group )
+	local tag = EMAUtilities:Lowercase( group )
+	-- Cannot add a system tag.
+	if IsASystemGroup( tag ) == false then
+		-- Cannot add a tag that already exists.
+		if DoesGroupExist( tag ) == false then
+			-- Add tag, resort and display.
+			AddGroup( tag )
+			EMA:SettingsGroupListScrollRefresh()
+		end
+	end
+end
+
+function EMA:RemoveTagGUI()
+	local tag = GetGroupAtPosition( EMA.settingsControl.groupListHighlightRow )
+	-- Cannot remove a system tag.
+	if IsASystemGroup( tag ) == false then
+		RemoveGroup( tag )
+	end
+end
+
+-- Add Group to group list from the command line.
+function EMA:AddTagCommand( info, parameters )
+	local tag = EMAUtilities:Lowercase( parameters )
+	--local characterName, tag = strsplit( " ", inputText )
+	if IsASystemGroup( tag ) == false then
+		-- Cannot add a tag that already exists.
+		if DoesGroupExist( tag ) == false then
+			AddGroup( tag )
+			EMA:SettingsGroupListScrollRefresh()
+		end
+	end
+end
+
+-- Add Group to group list from the command line.
+function EMA:AddToGroupCommand( info, parameters )
+	--local inputText = EMAUtilities:Lowercase( parameters )
+	local characterName, tag = strsplit( " ", parameters )
+	if characterName ~= nil or tag ~= nil then
+		local group = EMAUtilities:Lowercase( tag )
+		if DoesGroupExist( group ) == true then
+			local isInTeam, fullCharacterName = EMAPrivate.Team.IsCharacterInTeam( characterName )
+			--EMA:Print("isInTeam", isInTeam, fullCharacterName, group )
+			AddCharacterToGroup( fullCharacterName, group )
+		end
+	else
+	EMA:Print("[PH]"..L["WRONG_TEXT_INPUT_GROUP"] )
+	end
+end
+
+
+-- Remove tag from character from the command line.
+function EMA:RemoveTagCommand( info, parameters )
+	local inputText = EMAUtilities:Lowercase( parameters )
+	local characterName, tag = strsplit( " ", inputText )
+
+
+end
+
+function EMA:OnMasterChanged( message, characterName )
+	CheckSystemTagsAreCorrect()
+	EMA:SettingsRefresh()
+end
+
+function EMA:OnCharacterAdded( message, characterName )
+	CheckSystemTagsAreCorrect()
+	EMA:SettingsRefresh()
+end
+
+function EMA:OnCharacterRemoved( message, characterName )
+	EMA.db.tagList[characterName] = nil
+	EMA:SettingsRefresh()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Callbacks.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:SettingsGroupListScrollRefresh()
+	FauxScrollFrame_Update(
+		EMA.settingsControl.groupList.listScrollFrame,
+		GetGroupListMaximumOrder(),
+		EMA.settingsControl.groupList.rowsToDisplay,
+		EMA.settingsControl.groupList.rowHeight
+	)
+	EMA.settingsControl.groupListOffset = FauxScrollFrame_GetOffset( EMA.settingsControl.groupList.listScrollFrame )
+	for iterateDisplayRows = 1, EMA.settingsControl.groupList.rowsToDisplay do
+		-- Reset.
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetText( "" )
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].highlight:SetColorTexture( 0.0, 0.0, 0.0, 0.0 )
+		-- Get data.
+		local dataRowNumber = iterateDisplayRows + EMA.settingsControl.groupListOffset
+		if dataRowNumber <= GetGroupListMaximumOrder() then
+			-- Put character name into columns.
+			local group = GetGroupAtPosition( dataRowNumber )
+			local groupName = EMAUtilities:Capitalise( group )
+			EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetText( groupName )
+			-- System tags are Yellow.
+			if IsASystemGroup( group ) == true then
+				EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 0.96, 0.41, 1.0 )
+			end
+			-- Highlight the selected row.
+			if dataRowNumber == EMA.settingsControl.groupListHighlightRow then
+				EMA.settingsControl.groupList.rows[iterateDisplayRows].highlight:SetColorTexture( 1.0, 1.0, 0.0, 0.5 )
+			end
+		end
+	end
+end
+
+function EMA:SettingsGroupListRowClick( rowNumber, columnNumber )
+	if EMA.settingsControl.groupListOffset + rowNumber <= GetGroupListMaximumOrder() then
+		EMA.settingsControl.groupListHighlightRow = EMA.settingsControl.groupListOffset + rowNumber
+		EMA:SettingsGroupListScrollRefresh()
+	end
+end
+
+function EMA:SettingsPushSettingsClick( event )
+	EMA:EMASendSettings()
+end
+
+function EMA:SettingsAddClick( event )
+	StaticPopup_Show( "EMATAG_ASK_TAG_NAME" )
+end
+
+function EMA:SettingsRemoveClick( event )
+	local group = GetGroupAtPosition( EMA.settingsControl.groupListHighlightRow )
+	StaticPopup_Show( "EMATAG_CONFIRM_REMOVE_TAG", group )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Addon initialization, enabling and disabling.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialise the module.
+function EMA:OnInitialize()
+	-- Current character tag list.
+	EMA.characterTagList = {}
+	-- Create the settings control.
+	SettingsCreate()
+	-- Initialise the EMAModule part of this module.
+	EMA:EMAModuleInitialize( EMA.settingsControl.widgetSettings.frame )
+	-- Populate the settings.
+	EMA:SettingsRefresh()
+	-- Initialise the popup dialogs.
+	InitializePopupDialogs()
+	-- Initialise the all tags list.
+	EMA:InitializeAllTagsList()
+end
+
+-- Called when the addon is enabled.
+function EMA:OnEnable()
+	-- Make sure all the system tags are correct.
+	CheckSystemTagsAreCorrect()
+	EMA:RegisterMessage( EMAPrivate.Team.MESSAGE_TEAM_MASTER_CHANGED, "OnMasterChanged" )
+	EMA:RegisterMessage( EMAPrivate.Team.MESSAGE_TEAM_CHARACTER_ADDED, "OnCharacterAdded" )
+	EMA:RegisterMessage( EMAPrivate.Team.MESSAGE_TEAM_CHARACTER_REMOVED, "OnCharacterRemoved" )
+	-- Kickstart the settings team and tag list scroll frame.
+	EMA:SettingsGroupListScrollRefresh()
+	-- Click the first row in the team list table to populate the tag list table.
+	EMA:SettingsGroupListRowClick( 1, 1 )
+end
+
+-- Called when the addon is disabled.
+function EMA:OnDisable()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Commands.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:EMAOnCommandReceived( sender, commandName, ... )
+end
+
+-- Functions available for other addons EMA-EE > v8
+-- Group List API
+EMAApi.GroupList = GroupList
+EMAApi.GROUP_LIST_CHANGED = EMA.GROUP_LIST_CHANGED
+EMAApi.DoesGroupExist = DoesGroupExist
+EMAApi.IsASystemGroup = IsASystemGroup
+EMAApi.GetGroupListMaximumOrder = GetGroupListMaximumOrder
+EMAApi.GetGroupAtPosition = GetGroupAtPosition
+EMAApi.AddGroup = AddGroup
+EMAApi.RemoveGroup = RemoveGroup
+
+--Character Group API
+EMAApi.TeamGroupList = TeamGroupList
+EMAApi.IsCharacterInGroup = IsCharacterInGroup
+EMAApi.GetGroupListForCharacter = GetGroupListForCharacter
+EMAApi.CharacterMaxGroups = CharacterMaxGroups
+EMAApi.AddCharacterToGroup = AddCharacterToGroup
+EMAApi.RemoveGroupFromCharacter = RemoveGroupFromCharacter
+--EMAApi.CharacterAlreadyInGroup = CharacterAlreadyInGroup
+EMAApi.PushGroupSettings = EMA.SettingsPushSettingsClick
+
+-- SystemTags API
+EMAApi.AllGroup = AllTag
+EMAApi.MasterGroup = MasterTag
+EMAApi.MinionGroup = MinionTag
+
+-- Old Way, most modules need to be rewiren/udated to support the new API
+-- but for now we should keep this here incase we Mass Up Somewhere -- Ebony
+EMAPrivate.Tag.MasterTag = MasterTag
+EMAPrivate.Tag.MinionTag = MinionTag
+EMAPrivate.Tag.AllTag = AllTag
+EMAPrivate.Tag.DoesCharacterHaveTag = IsCharacterInGroup
+EMAApi.DoesCharacterHaveTag = IsCharacterInGroup
+EMAApi.AllTag = AllTag
diff --git a/Core/Team-Classic.lua b/Core/Team-Classic.lua
new file mode 100644
index 0000000..f6b6ef0
--- /dev/null
+++ b/Core/Team-Classic.lua
@@ -0,0 +1,2179 @@
+-- ================================================================================ --
+--				EMA - ( Ebony's MultiBoxing Assistant )    							--
+--				Current Author: Jennifer Cally (Ebony)								--
+--																					--
+--				License: All Rights Reserved 2018-2019 Jennifer Cally					--
+--																					--
+--				Some Code Used from "Jamba" that is 								--
+--				Released under the MIT License 										--
+--				"Jamba" Copyright 2008-2015  Michael "Jafula" Miller				--
+--																					--
+-- ================================================================================ --
+
+-- Create the addon using AceAddon-3.0 and embed some libraries.
+local EMA = LibStub( "AceAddon-3.0" ):NewAddon(
+	"Team",
+	"Module-1.0",
+	"AceConsole-3.0",
+	"AceEvent-3.0",
+	"AceHook-3.0",
+	"AceTimer-3.0"
+)
+
+-- Load libraries.
+local EMAUtilities = LibStub:GetLibrary( "EbonyUtilities-1.0" )
+local EMAHelperSettings = LibStub:GetLibrary( "EMAHelperSettings-1.0" )
+
+-- Constants required by EMAModule and Locale for this module.
+EMA.moduleName = "Team"
+EMA.settingsDatabaseName = "TeamProfileDB"
+EMA.chatCommand = "ema-team"
+local L = LibStub( "AceLocale-3.0" ):GetLocale( "Core" )
+EMA.parentDisplayName = L["TEAM"]
+EMA.moduleDisplayName = L["TEAM"]
+-- Icon
+EMA.moduleIcon = "Interface\\Addons\\EMA-Classic\\Media\\TeamCore.tga"
+-- order
+EMA.moduleOrder = 20
+
+
+-- EMA key bindings.
+BINDING_HEADER_TEAM = L["TEAM"]
+BINDING_NAME_TEAMINVITE = L["INVITE_GROUP"]
+BINDING_NAME_TEAMDISBAND = L["DISBAND_GROUP"]
+BINDING_NAME_TEAMMASTER = L["SET_MASTER"]
+
+-- Settings - the values to store and their defaults for the settings database.
+EMA.settings = {
+	profile = {
+		master = "",
+        teamList = {},
+		newTeamList = {},
+		masterChangePromoteLeader = false,
+		inviteAcceptTeam = true,
+		inviteAcceptFriends = false,
+		inviteAcceptGuild = false,
+		inviteDeclineStrangers = false,
+		inviteConvertToRaid = true,
+		inviteSetAllAssistant = false,
+		masterChangeClickToMove = false,
+		lootSetAutomatically = false,
+		lootSetFreeForAll = true,
+		lootSetMasterLooter = false,
+		lootSlavesOptOutOfLoot = false,
+		lootToGroupIfStrangerPresent = true,
+		lootToGroupFriendsAreNotStrangers = false,
+	},
+}
+
+-- Configuration.
+function EMA:GetConfiguration()
+	local configuration = {
+		name = EMA.moduleDisplayName,
+		handler = EMA,
+		type = "group",
+		get = "EMAConfigurationGetSetting",
+		set = "EMAConfigurationSetSetting",
+		args = {
+			config = {
+				type = "input",
+				name = L["OPEN_CONFIG"],
+				desc = L["OPEN_CONFIG_HELP"],
+				usage = "/ema-team config",
+				get = false,
+				set = "",
+			},
+			add = {
+				type = "input",
+				name = L["ADD"],
+				desc = L["ADD_HELP"],
+				usage = "/ema-team add <name>",
+				get = false,
+				set = "AddMemberCommand",
+			},
+			remove = {
+				type = "input",
+				name = L["REMOVE"],
+				desc = L["REMOVE_REMOVE"],
+				usage = "/ema-team remove <name>",
+				get = false,
+				set = "RemoveMemberCommand",
+			},
+			master = {
+				type = "input",
+				name = L["MASTER"],
+				desc = L["MASTER_HELP"],
+				usage = "/ema-team master <name> <tag>",
+				get = false,
+				set = "CommandSetMaster",
+			},
+			iammaster = {
+				type = "input",
+				name = L["I_AM_MASTER"],
+				desc = L["I_AM_MASTER_HELP"],
+				usage = "/ema-team iammaster <tag>",
+				get = false,
+				set = "CommandIAmMaster",
+			},
+			invite = {
+				type = "input",
+				name = L["INVITE"],
+				desc = L["INVITE_HELP"],
+				usage = "/ema-team invite",
+				get = false,
+				set = "InviteTeamToParty",
+			},
+			disband = {
+				type = "input",
+				name = L["DISBAND"],
+				desc = L["DISBAND_HELP"],
+				usage = "/ema-team disband",
+				get = false,
+				set = "DisbandTeamFromParty",
+			},
+			addparty = {
+				type = "input",
+				name = L["ADD_GROUPS_MEMBERS"],
+				desc = L["ADD_GROUPS_MEMBERS_HELP"],
+				usage = "/ema-team addparty",
+				get = false,
+				set = "AddPartyMembers",
+			},
+			removeall = {
+				type = "input",
+				name = L["REMOVE_ALL_MEMBERS"],
+				desc = L["REMOVE_ALL_MEMBERS_HELP"],
+				usage = "/ema-team removeall",
+				get = false,
+				set = "DoRemoveAllMembersFromTeam",
+			},
+			setalloffline = {
+				type = "input",
+				name = L["SET_TEAM_OFFLINE"],
+				desc = L["SET_TEAM_OFFLINE_HELP"] ,
+				usage = "/ema-team setalloffline",
+				get = false,
+				set = "SetAllMembersOffline",
+			},
+			setallonline = {
+				type = "input",
+				name = L["SET_TEAM_ONLINE"],
+				desc = L["SET_TEAM_ONLINE_HELP"],
+				usage = "/ema-team setallonline",
+				get = false,
+				set = "SetAllMembersOnline",
+			},
+			push = {
+				type = "input",
+				name = L["PUSH_SETTINGS"],
+				desc = L["PUSH_SETTINGS_INFO"],
+				usage = "/ema-team push",
+				get = false,
+				set = "EMASendSettings",
+			},
+		},
+	}
+	return configuration
+end
+
+-- Create the character online table and ordered characters tables.
+EMA.orderedCharacters = {}
+EMA.orderedCharactersOnline = {}
+
+-------------------------------------------------------------------------------------------------------------
+-- Command this module sends.
+-------------------------------------------------------------------------------------------------------------
+
+EMA.COMMAND_TAG_PARTY = "EMATeamTagGroup"
+-- Leave party command.
+EMA.COMMAND_LEAVE_PARTY = "EMATeamLeaveGroup"
+-- Set master command.
+EMA.COMMAND_SET_MASTER = "EMATeamSetMaster"
+-- Set Minion OffLine
+EMA.COMMAND_SET_OFFLINE = "EMATeamSetOffline"
+EMA.COMMAND_SET_ONLINE = "EMATeamSetOnline"
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Messages module sends.
+-------------------------------------------------------------------------------------------------------------
+
+-- Master changed, parameter: new master name.
+EMA.MESSAGE_TEAM_MASTER_CHANGED = "EMATeamMasterChanged"
+-- Team order changed, no parameters.
+EMA.MESSAGE_TEAM_ORDER_CHANGED = "EMATeamOrderChanged"
+-- Character has been added, parameter: characterName.
+EMA.MESSAGE_TEAM_CHARACTER_ADDED = "EMATeamCharacterAdded"
+-- Character has been removed, parameter: characterName.
+EMA.MESSAGE_TEAM_CHARACTER_REMOVED = "EMATeamCharacterRemoved"
+-- character online
+EMA.MESSAGE_CHARACTER_ONLINE = "JmbTmChrOn"
+-- character offline
+EMA.MESSAGE_CHARACTER_OFFLINE = "JmbTmChrOf"
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Constants used by module.
+-------------------------------------------------------------------------------------------------------------
+
+EMA.simpleAreaList = {}
+EMA.PARTY_LOOT_FREEFORALL = "freeforall"
+EMA.PARTY_LOOT_GROUP = "group"
+EMA.PARTY_LOOT_MASTER = "master"
+EMA.PARTY_LOOT_NEEDBEFOREGREED = "needbeforegreed"
+EMA.PARTY_LOOT_ROUNDROBIN = "roundrobin"
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+local function SettingsCreateTeamList()
+	-- Position and size constants.
+	local teamListButtonControlWidth = 250
+	local iconSize = 24
+	local groupListWidth = 200
+	local extaSpacing = 40
+	local rowHeight = 30
+	local rowsToDisplay = 8
+	local inviteDisbandButtonWidth = 105
+	local setMasterButtonWidth = 120
+	local buttonHeight = EMAHelperSettings:GetButtonHeight()
+	local top = EMAHelperSettings:TopOfSettings()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local dropdownHeight = EMAHelperSettings:GetDropdownHeight()
+	local lefticon =  left + 35
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local dropBoxWidth = (headingWidth - horizontalSpacing) / 4
+	local iconHight = iconSize + 10
+	local teamListWidth = headingWidth - teamListButtonControlWidth - horizontalSpacing
+	local leftOfList = left + horizontalSpacing
+	local rightOfList = teamListWidth + horizontalSpacing
+	local checkBoxWidth = (headingWidth - horizontalSpacing) / 2
+	local topOfList = top - headingHeight
+	local movingTop = top
+	-- Team list internal variables (do not change).
+	EMA.settingsControl.teamListHighlightRow = 1
+	EMA.settingsControl.teamListOffset = 1
+	-- A blank to get layout to show right?
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L[""], movingTop, false )
+	movingTop = movingTop - headingHeight
+	EMA.settingsControl.labelOne = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		teamListButtonControlWidth,
+		teamListWidth / 2,
+		leftOfList,
+		L["TEAM_HEADER"]
+	)
+	EMA.settingsControl.labelTwo = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		teamListButtonControlWidth,
+
+		teamListButtonControlWidth + iconSize + groupListWidth,
+		leftOfList,
+		L["GROUPS_HEADER"]
+	)
+	-- Create a team list frame.
+	local list = {}
+	list.listFrameName = "EMATeamSettingsTeamListFrame"
+	list.parentFrame = EMA.settingsControl.widgetSettings.content
+	list.listTop = topOfList
+	list.listLeft = lefticon
+	list.listWidth = teamListWidth
+	list.rowHeight = rowHeight
+	list.rowsToDisplay = rowsToDisplay
+	list.columnsToDisplay = 3
+	list.columnInformation = {}
+	list.columnInformation[1] = {}
+	list.columnInformation[1].width = 30
+	list.columnInformation[1].alignment = "LEFT"
+	list.columnInformation[2] = {}
+	list.columnInformation[2].width = 55
+	list.columnInformation[2].alignment = "CENTER"
+	list.columnInformation[3] = {}
+	list.columnInformation[3].width = 15
+	list.columnInformation[3].alignment = "RIGHT"
+	list.scrollRefreshCallback = EMA.SettingsTeamListScrollRefresh
+	list.rowClickCallback = EMA.SettingsTeamListRowClick
+	EMA.settingsControl.teamList = list
+	EMAHelperSettings:CreateScrollList( EMA.settingsControl.teamList )
+	-- Group Frame
+	local listTwo = {}
+	listTwo.listFrameName = "EMATeamSettingsTeamListTwoFrame"
+	listTwo.parentFrame = EMA.settingsControl.widgetSettings.content
+	listTwo.listTop = topOfList
+	listTwo.listLeft = rightOfList + extaSpacing
+	listTwo.listWidth = groupListWidth
+	listTwo.rowHeight = rowHeight
+	listTwo.rowsToDisplay = rowsToDisplay
+	listTwo.columnsToDisplay = 1
+	listTwo.columnInformation = {}
+	listTwo.columnInformation[1] = {}
+	listTwo.columnInformation[1].width = 80
+	listTwo.columnInformation[1].alignment = "CENTER"
+	listTwo.scrollRefreshCallback = EMA.SettingsGroupListScrollRefresh
+	listTwo.rowClickCallback = EMA.SettingsGroupListRowClick
+	EMA.settingsControl.groupList = listTwo
+	EMAHelperSettings:CreateScrollList( EMA.settingsControl.groupList )
+	-- Position and size constants (once list height is known).
+	local bottomOfList = topOfList - list.listHeight - verticalSpacing
+	local bottomOfSection = bottomOfList -  dropdownHeight - verticalSpacing
+	--Create Icons
+	EMA.settingsControl.teamListButtonAdd = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharAdd.tga", --icon Image
+		left - iconSize - 11 ,
+		topOfList - verticalSpacing,
+		L[""],
+		EMA.SettingsAddClick,
+		L["BUTTON_ADD_HELP"]
+	)
+	EMA.settingsControl.teamListButtonParty = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharAddParty.tga", --icon Image
+		left - iconSize - 11 ,
+		topOfList - verticalSpacing - iconHight,
+		L[""],
+		EMA.SettingsAddPartyClick,
+		L["BUTTON_ADDALL_HELP"]
+	)
+	EMA.settingsControl.teamListButtonAddIsboxerList = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\Isboxer_Add.tga", --icon Image
+		left - iconSize - 11 ,
+		topOfList - verticalSpacing - iconHight * 2,
+		L[""],
+		EMA.SettingsAddIsboxerListClick,
+		L["BUTTON_ISBOXER_ADD_HELP"]
+	)
+	EMA.settingsControl.teamListButtonMoveUp = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharUp.tga", --icon Image
+		left - iconSize - 11,
+		topOfList - verticalSpacing - iconHight * 3,
+		L[""],
+		EMA.SettingsMoveUpClick,
+		L["BUTTON_UP_HELP"]
+	)
+	EMA.settingsControl.teamListButtonMoveDown = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharDown.tga", --icon Image
+		left - iconSize - 11,
+		topOfList - verticalSpacing - iconHight * 4,
+		L[""],
+		EMA.SettingsMoveDownClick,
+		L["BUTTON_DOWN_HELP"]
+	)
+	EMA.settingsControl.teamListButtonRemove = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharRemove.tga", --icon Image
+		left - iconSize - 11 ,
+		topOfList - verticalSpacing - iconHight * 5,
+		L[""],
+		EMA.SettingsRemoveClick,
+		L["BUTTON_REMOVE_HELP"]
+	)
+	EMA.settingsControl.teamListButtonSetMaster = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharMaster.tga", --icon Image
+		left - iconSize - 11 ,
+		topOfList - verticalSpacing - iconHight * 6,
+		L[""],
+		EMA.SettingsSetMasterClick,
+		L["BUTTON_MASTER_HELP"]
+	)
+	EMA.settingsControl.teamListButtonRemoveFromGroup = EMAHelperSettings:Icon(
+		EMA.settingsControl,
+		iconSize,
+		iconSize,
+		"Interface\\Addons\\EMA-Classic\\Media\\CharRemoveParty.tga", --icon Image
+		rightOfList + dropBoxWidth + 11 ,
+		bottomOfList ,
+		L[""],
+		EMA.SettingsRemoveGroupClick,
+		L["BUTTON_GROUP_REMOVE_HELP"]
+	)
+	-- Group Mangent
+	EMA.settingsControl.teamListDropDownList = EMAHelperSettings:CreateDropdown(
+		EMA.settingsControl,
+		dropBoxWidth,
+		rightOfList + extaSpacing, -- horizontalSpacing,
+		bottomOfList + 11,
+		L["GROUP_LIST"]
+	)
+	EMA.settingsControl.teamListDropDownList:SetList( EMA.GroupAreaList() )
+	EMA.settingsControl.teamListDropDownList:SetCallback( "OnValueChanged",  EMA.TeamListDropDownList )
+	return bottomOfSection
+end
+
+local function SettingsCreateMasterControl( top )
+	-- Get positions.
+	local checkBoxHeight = EMAHelperSettings:GetCheckBoxHeight()
+	local labelContinueHeight = EMAHelperSettings:GetContinueLabelHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local checkBoxWidth = (headingWidth - horizontalSpacing) / 2
+	local column1Left = left
+	local column2Left = left + checkBoxWidth + horizontalSpacing
+	local bottomOfSection = top - headingHeight - (checkBoxHeight * 1) - (verticalSpacing * 3)
+	-- Create a heading.
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["MASTER_CONTROL"], top, false )
+	-- Create checkboxes.
+
+	EMA.settingsControl.masterControlCheckBoxMasterChange = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight,
+		L["CHECKBOX_MASTER_LEADER"],
+		EMA.SettingsMasterChangeToggle,
+		L["CHECKBOX_MASTER_LEADER_HELP"]
+	)
+	EMA.settingsControl.masterControlCheckBoxMasterChangeClickToMove = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column2Left,
+		top - headingHeight,
+		L["CHECKBOX_CTM"],
+		EMA.SettingsMasterChangeClickToMoveToggle,
+		L["CHECKBOX_CTM_HELP"]
+	)
+	return bottomOfSection
+end
+
+local function SettingsCreatePartyInvitationsControl( top )
+	-- Get positions.
+	local checkBoxHeight = EMAHelperSettings:GetCheckBoxHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local checkBoxWidth = (headingWidth - horizontalSpacing) / 2
+	local column1Left = left
+	local column2Left = left + checkBoxWidth + horizontalSpacing
+	local bottomOfSection = top - headingHeight - (checkBoxHeight * 4) - (verticalSpacing * 2)
+	-- Create a heading.
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["PARTY_CONTROLS"], top, false )
+	-- Create checkboxes.
+	EMA.settingsControl.partyInviteControlCheckBoxConvertToRaid = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight,
+		L["CHECKBOX_CONVERT_RAID"],
+		EMA.SettingsinviteConvertToRaidToggle,
+		L["CHECKBOX_CONVERT_RAID_HELP"]
+	)
+	EMA.settingsControl.partyInviteControlCheckBoxSetAllAssist = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column2Left,
+		top - headingHeight,
+		L["CHECKBOX_ASSISTANT"],
+		EMA.SettingsinviteSetAllAssistToggle,
+		L["CHECKBOX_ASSISTANT_HELP"]
+	)
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptMembers = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight - checkBoxHeight,
+		L["CHECKBOX_TEAM"],
+		EMA.SettingsAcceptInviteMembersToggle,
+		L["CHECKBOX_TEAM_HELP"]
+	)
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptFriends = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column2Left,
+		top - headingHeight - checkBoxHeight,
+		L["CHECKBOX_ACCEPT_FROM_FRIENDS"],
+		EMA.SettingsAcceptInviteFriendsToggle,
+		L["CHECKBOX_ACCEPT_FROM_FRIENDS_HELP"]
+	)
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptGuild = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight - checkBoxHeight - checkBoxHeight,
+		L["CHECKBOX_ACCEPT_FROM_GUILD"],
+		EMA.SettingsAcceptInviteGuildToggle,
+		L["CHECKBOX_ACCEPT_FROM_GUILD_HELP"]
+	)
+	EMA.settingsControl.partyInviteControlCheckBoxDeclineStrangers = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight  - checkBoxHeight - checkBoxHeight - checkBoxHeight,
+		L["CHECKBOX_DECLINE_STRANGERS"],
+		EMA.SettingsDeclineInviteStrangersToggle,
+		L["CHECKBOX_DECLINE_STRANGERS_HELP"]
+	)
+	return bottomOfSection
+end
+
+local function SettingsCreatePartyLootControl( top )
+	-- Get positions.
+	local checkBoxHeight = EMAHelperSettings:GetCheckBoxHeight()
+	local radioBoxHeight = EMAHelperSettings:GetRadioBoxHeight()
+	local labelContinueHeight = EMAHelperSettings:GetContinueLabelHeight()
+	local left = EMAHelperSettings:LeftOfSettings()
+	local headingHeight = EMAHelperSettings:HeadingHeight()
+	local headingWidth = EMAHelperSettings:HeadingWidth( false )
+	local horizontalSpacing = EMAHelperSettings:GetHorizontalSpacing()
+	local verticalSpacing = EMAHelperSettings:GetVerticalSpacing()
+	local checkBoxWidth = (headingWidth - horizontalSpacing) / 2
+	local indentContinueLabel = horizontalSpacing * 13
+	local column1Left = left
+	local column2Left = left + checkBoxWidth + horizontalSpacing
+	local bottomOfSection = top - headingHeight - checkBoxHeight - radioBoxHeight - verticalSpacing - checkBoxHeight - checkBoxHeight - labelContinueHeight - (verticalSpacing * 4) - labelContinueHeight - checkBoxHeight
+
+	-- Create a heading.
+	EMAHelperSettings:CreateHeading( EMA.settingsControl, L["PARTY_LOOT_CONTROL"], top, false )
+
+	-- Create checkboxes.
+	EMA.settingsControl.partyLootControlCheckBoxSetLootMethod = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		top - headingHeight,
+		L["SET_LOOT_METHOD"],
+		EMA.SettingsSetLootMethodToggle,
+		L["SET_LOOT_METHOD_HELP"]
+	)
+	-- Label continuing check box above.
+	EMA.settingsControl.labelPartyLootControlCheckBoxSetLootMethod = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left + indentContinueLabel,
+		top - headingHeight - checkBoxHeight,
+		L["TO"]
+	)
+	EMA.settingsControl.partyLootControlCheckBoxSetFFA = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column1Left,
+		top - headingHeight - checkBoxHeight - labelContinueHeight - verticalSpacing,
+		L["FFA"],
+		EMA.SettingsSetFFALootToggle,
+		L["FFA_HELP"]
+	)
+	EMA.settingsControl.partyLootControlCheckBoxSetFFA:SetType( "radio" )
+	EMA.settingsControl.partyLootControlCheckBoxSetMasterLooter = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		checkBoxWidth,
+		column2Left,
+		top - headingHeight - checkBoxHeight - labelContinueHeight - verticalSpacing,
+		L["MASTER_LOOTER"],
+		EMA.SettingsSetMasterLooterToggle,
+		L["MASTER_LOOTER_HELP"]
+	)
+	EMA.settingsControl.partyLootControlCheckBoxSetMasterLooter:SetType( "radio" )
+	EMA.settingsControl.partyLootControlCheckBoxStrangerToGroup = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		top - headingHeight - checkBoxHeight - radioBoxHeight - labelContinueHeight,
+		L["LOOT_STRANGER"],
+		EMA.SettingsSetStrangerToGroup,
+		L["LOOT_STRANGER_HELP"]
+	)
+	-- Label continuing check box above.
+	EMA.settingsControl.labelPartyLootControlCheckBoxStrangerToGroup = EMAHelperSettings:CreateContinueLabel(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left + indentContinueLabel,
+		top - headingHeight - checkBoxHeight - radioBoxHeight - labelContinueHeight - (verticalSpacing * 4) - labelContinueHeight,
+		L["IN_GROUP"]
+	)
+	EMA.settingsControl.partyLootControlCheckBoxFriendsNotStrangers = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left + indentContinueLabel,
+		top - headingHeight - checkBoxHeight - radioBoxHeight - checkBoxHeight - labelContinueHeight - labelContinueHeight,
+		L["FRIENDS_NOT_STRANGERS"],
+		EMA.SettingsSetFriendsNotStrangers,
+		L["FRIENDS_NOT_STRANGERS_HELP"]
+	)
+	EMA.settingsControl.partyLootControlCheckBoxSetOptOutOfLoot = EMAHelperSettings:CreateCheckBox(
+		EMA.settingsControl,
+		headingWidth,
+		column1Left,
+		top - headingHeight - checkBoxHeight - radioBoxHeight - checkBoxHeight - labelContinueHeight - labelContinueHeight - checkBoxHeight ,
+		L["OOOL"],
+		EMA.SettingsSetSlavesOptOutToggle,
+		L["OOOL_HELP"]
+	)
+	return bottomOfSection
+end
+
+local function SettingsCreate()
+	EMA.settingsControl = {}
+	-- Create the settings panel.
+	EMAHelperSettings:CreateSettings(
+		EMA.settingsControl,
+		EMA.moduleDisplayName,
+		EMA.parentDisplayName,
+		EMA.SettingsPushSettingsClick,
+		EMA.moduleIcon,
+		EMA.moduleOrder
+	)
+	-- Create the team list controls.
+	local bottomOfTeamList = SettingsCreateTeamList()
+	-- Create the master control controls.
+	local bottomOfMasterControl = SettingsCreateMasterControl( bottomOfTeamList )
+	-- Create the party invitation controls.
+	local bottomOfPartyInvitationControl = SettingsCreatePartyInvitationsControl( bottomOfMasterControl )
+	EMA.settingsControl.widgetSettings.content:SetHeight( - bottomOfMasterControl )
+	-- Create the party loot control controls.
+	local bottomOfPartyLootControl = SettingsCreatePartyLootControl( bottomOfPartyInvitationControl )
+	EMA.settingsControl.widgetSettings.content:SetHeight( -bottomOfPartyLootControl )
+	-- Help
+	local helpTable = {}
+	EMAHelperSettings:CreateHelp( EMA.settingsControl, helpTable, EMA:GetConfiguration() )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Popup Dialogs.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialize Popup Dialogs.
+local function InitializePopupDialogs()
+   -- Ask the name of the character to add as a new member.
+   StaticPopupDialogs["EMATEAM_ASK_CHARACTER_NAME"] = {
+        text = L["STATICPOPUP_ADD"],
+        button1 = ACCEPT,
+        button2 = CANCEL,
+        hasEditBox = 1,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+		OnShow = function( self )
+			self.editBox:SetText("")
+            self.button1:Disable()
+            self.editBox:SetFocus()
+        end,
+		OnAccept = function( self )
+			EMA:AddMemberGUI( self.editBox:GetText() )
+		end,
+		EditBoxOnTextChanged = function( self )
+            if not self:GetText() or self:GetText():trim() == "" then
+				self:GetParent().button1:Disable()
+            else
+                self:GetParent().button1:Enable()
+            end
+        end,
+		EditBoxOnEnterPressed = function( self )
+            if self:GetParent().button1:IsEnabled() then
+				EMA:AddMemberGUI( self:GetText() )
+            end
+            self:GetParent():Hide()
+        end,
+    }
+   -- Confirm removing characters from member list.
+   StaticPopupDialogs["EMATEAM_CONFIRM_REMOVE_CHARACTER"] = {
+        text = L["STATICPOPUP_REMOVE"],
+        button1 = ACCEPT,
+        button2 = CANCEL,
+        timeout = 0,
+		whileDead = 1,
+		hideOnEscape = 1,
+        OnAccept = function( self )
+			EMA:RemoveMemberGUI()
+		end,
+    }
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Team management.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:GroupAreaList()
+	table.sort( EMA.simpleAreaList )
+	return EMA.simpleAreaList
+end
+
+local function refreshDropDownList()
+	EMAUtilities:ClearTable( EMA.simpleAreaList )
+	EMA.simpleAreaList[" "] = " "
+	for id, tag in pairs( EMAApi.GroupList() ) do
+		local groupName =  EMAUtilities:Capitalise( tag )
+		EMA.simpleAreaList[groupName] = groupName
+	end
+	table.sort( EMA.simpleAreaList )
+	EMA.settingsControl.teamListDropDownList:SetList( EMA.simpleAreaList )
+end
+
+local function TeamList()
+	--return pairs( EMA.db.teamList )
+	local teamlist = {}
+	for name, info in pairs( EMA.db.newTeamList ) do
+		for _, charInfo in pairs (info) do
+			teamlist[name] = charInfo.order
+		end
+	end
+	return pairs( teamlist )
+end
+
+
+local function FullTeamList()
+	local fullTeamList = {}
+	for name, info in pairs ( EMA.db.newTeamList ) do
+		for _, charInfo in pairs (info) do
+		table.insert(fullTeamList, { charInfo.name, charInfo.order, charInfo.class, charInfo.online } )
+		end
+	end
+	return pairs( fullTeamList )
+end
+
+local function setClass()
+	for characterName, position in pairs( EMA.db.newTeamList ) do
+	local class, classFileName, classIndex = UnitClass( Ambiguate(characterName, "none") )
+		--EMA:Print("new", class, CharacterName )
+		if class ~= nil then
+			EMA.db.characterClass[characterName] = classFileName
+		end
+	end
+end
+
+local function GetClass( characterName )
+	local class = nil
+	local color = nil
+	for teamCharacterName, info in pairs( EMA.db.newTeamList ) do
+		if characterName == teamCharacterName then
+			for _, charInfo in pairs (info) do
+			--charInfo.class
+				--EMA:Print("classDatatest",  characterName, charInfo.class )
+				if charInfo.class ~= nil or charInfo.class ~= "UNKNOWN" then
+					class = EMAUtilities:Lowercase( charInfo.class )
+					color = RAID_CLASS_COLORS[charInfo.class]
+				end
+			end
+		end
+	end
+	return class, color
+end
+
+-- Get the largest order number from the team list.
+local function GetTeamListMaximumOrder()
+	local largestPosition = 0
+	for characterName, position in EMAApi.TeamList() do
+		if position > largestPosition then
+			largestPosition = position
+		end
+	end
+	return largestPosition
+end
+
+local function GetTeamListMaximumOrderOnline()
+	local totalMembersDisplayed = 0
+		for characterName, position in EMAApi.TeamList() do
+			if EMAApi.GetCharacterOnlineStatus( characterName ) == true then
+				totalMembersDisplayed = totalMembersDisplayed + 1
+			end
+		end
+	return totalMembersDisplayed
+end
+
+local function IsCharacterInTeam( name )
+	local characterName = EMAUtilities:Lowercase( name )
+	local fullCharacterName = nil
+	local isMember = false
+	if not isMember then
+		for fullTeamCharacterName, position in EMAApi.TeamList() do
+			local checkFullName = EMAUtilities:Lowercase( fullTeamCharacterName )
+			local name, realm = strsplit("-", checkFullName, 2 )
+			--EMA:Print('checking', name, 'vs', characterName, "or", checkFullName )
+			if name == characterName or checkFullName == characterName then
+				--EMA:Print('match found')
+				isMember = true
+				fullCharacterName = fullTeamCharacterName
+				break
+			end
+		end
+	end
+	--EMA:Print('returning', isMember)
+	return isMember, fullCharacterName
+end
+
+
+
+-- Get the master for this character.
+local function GetMasterName()
+	return EMA.db.master
+end
+
+-- Return true if the character specified is in the master.
+local function IsCharacterTheMaster( characterName )
+	local isTheMaster = false
+	if characterName == GetMasterName() then
+		isTheMaster = true
+	end
+	return isTheMaster
+end
+
+-- Set the master for EMA character; the master character must be online.
+local function SetMaster( master )
+	-- Make sure a valid string value is supplied.
+	if (master ~= nil) and (master:trim() ~= "") then
+		-- The name must be capitalised i still like this or though its not needed.
+		--local character = EMAUtilities:Capitalise( master )
+		local character = EMAUtilities:AddRealmToNameIfMissing( master )
+		-- Only allow characters in the team list to be the master.
+		if IsCharacterInTeam( character ) == true then
+			-- Set the master.
+			EMA.db.master = character
+			-- Refresh the settings.
+			EMA:SettingsRefresh()
+			-- Send a message to any listeners that the master has changed.
+			EMA:SendMessage( EMA.MESSAGE_TEAM_MASTER_CHANGED, character )
+		else
+			-- Character not in team.  Tell the team.
+			EMA:EMASendMessageToTeam( EMA.characterName, L["A_IS_NOT_IN_TEAM"]( character ), false )
+		end
+	end
+end
+
+-- Add a member to the member list.
+local function AddMember( importName, class )
+	--EMA:Print("testAddMembers", importName, class)
+	local name = nil
+	local singleName, realm = strsplit( "-" , importName, 2 )
+	local characterName = nil
+	local name = EMAUtilities:Capitalise( singleName )
+	if realm ~= nil then
+		characterName = name.."-"..realm
+	else
+		characterName = name
+	end
+	if characterName == "Target" then
+		local UnitIsPlayer = UnitIsPlayer("target")
+		if UnitIsPlayer == true then
+			local unitName = GetUnitName("target", true)
+			--EMA:Print("Target", unitName)
+			name = unitName
+		else
+			EMA:Print(L["TEAM_NO_TARGET"])
+			return
+		end
+	elseif characterName == "Mouseover"  then
+		local UnitIsPlayer = UnitIsPlayer("mouseover")
+		if UnitIsPlayer == true then
+			local unitName = GetUnitName("mouseover", true)
+			--EMA:Print("mouseover", unitName)
+			name = unitName
+		else
+			EMA:Print(L["TEAM_NO_TARGET"])
+			return
+		end
+	else
+		name = characterName
+	end
+	-- Wow names are at least two characters.
+	if name ~= nil and name:trim() ~= "" and name:len() > 1 then
+		-- If the character is not already in the list...
+		local character = EMAUtilities:AddRealmToNameIfMissing( name )
+		if EMA.db.newTeamList[character] == nil then
+			-- Get the maximum order number.
+			--Store TempData
+			local maxOrder = "0"
+			local CharacterClass = "UNKNOWN"
+			local Online = true
+			-- Real Data
+			local maxOrder = GetTeamListMaximumOrder()
+			if class ~= nil then
+				local upperClass = string.upper(class)
+				CharacterClass = upperClass
+			end
+			local _, classFileName = UnitClass( Ambiguate(character, "none") )
+			if classFileName ~= nil then
+				CharacterClass = classFileName
+			end
+			--EMA:Print("DebugAddToDB", "toon", character, "order", maxOrder, "class", CharacterClass, "online", Online )
+			EMA.db.newTeamList[character] = {}
+			table.insert( EMA.db.newTeamList[character], {name = character, order = maxOrder + 1, class = CharacterClass, online = Online } )
+			-- Send a message to any listeners that EMA character has been added.
+			EMA:SendMessage( EMA.MESSAGE_TEAM_CHARACTER_ADDED, character )
+			-- Refresh the settings.
+			EMA:SettingsRefresh()
+		end
+	end
+end
+
+-- Add all party/raid members to the member list. does not worl cross rwalm todo
+function EMA:AddPartyMembers()
+	 for iteratePartyMembers = 1, GetNumGroupMembers() do
+		--EMA:Print("party/raid", numberPartyMembers, iteratePartyMembers)
+		local inRaid = IsInRaid()
+		if inRaid == true then
+			local partyMemberName, partyMemberRealm = UnitName( "raid"..iteratePartyMembers )
+			local character = EMAUtilities:AddRealmToNameIfNotNil( partyMemberName, partyMemberRealm )
+			if partyMemberName ~= nil then
+				if IsCharacterInTeam( character ) == false then
+					AddMember( character )
+				end
+			end
+		else
+			local partyMemberName, partyMemberRealm = UnitName( "party"..iteratePartyMembers )
+			local character = EMAUtilities:AddRealmToNameIfNotNil( partyMemberName, partyMemberRealm )
+			if partyMemberName ~= nil then
+				if IsCharacterInTeam( character ) == false then
+					AddMember( character )
+				end
+			end
+		end
+	end
+end
+
+
+-- Add a member to the member list.
+function EMA:AddMemberGUI( value )
+	AddMember( value )
+	EMA:SettingsTeamListScrollRefresh()
+end
+
+-- Add member from the command line.
+function EMA:AddMemberCommand( info, parameters )
+	if info ~= nil then
+		AddMember( parameters )
+	end
+end
+
+-- Get the character name at a specific position.
+local function GetCharacterNameAtOrderPosition( position )
+	local characterNameAtPosition = ""
+	for characterName, characterPosition in EMAApi.TeamList() do
+		if characterPosition == position then
+			characterNameAtPosition = characterName
+			break
+		end
+	end
+	return characterNameAtPosition
+end
+
+-- Get the position for a specific character.
+local function GetPositionForCharacterName( findCharacterName )
+	local positionForCharacterName = 0
+	for name, info in pairs (EMA.db.newTeamList) do
+		for _, charInfo in pairs (info) do
+			if name == findCharacterName then
+				positionForCharacterName = charInfo.order
+			break
+			end
+		end
+	end
+
+	return positionForCharacterName
+end
+
+local function GetPositionForCharacterNameOnline( findCharacterName )
+	local positionForCharacterName = 0
+		for index, characterName in EMAApi.TeamListOrderedOnline() do
+			if characterName == findCharacterName then
+				--EMA:Print("found", characterName, index)
+				positionForCharacterName = index
+				--break
+			end
+	end
+	return positionForCharacterName
+end
+
+-- Swap character positions.
+local function TeamListSwapCharacterPositions( position1, position2 )
+	-- Get characters at positions.
+	local character1 = GetCharacterNameAtOrderPosition( position1 )
+	local character2 = GetCharacterNameAtOrderPosition( position2 )
+	for name, info in pairs (EMA.db.newTeamList) do
+		for _, charInfo in pairs (info) do
+			if name == character1 then
+				charInfo.order = position2
+			end
+			if name == character2 then
+				charInfo.order = position1
+			end
+		end
+	end
+end
+
+-- Makes sure that EMA character is a team member.  Enables if previously not a member.
+local function ConfirmCharacterIsInTeam()
+	--EMA:Print("test", EMA.characterName)
+	if not IsCharacterInTeam( EMA.characterName ) then
+		-- Then add as a member.
+		AddMember( EMA.characterName )
+	end
+end
+
+-- Make sure there is a master, if none, set this character.
+local function ConfirmThereIsAMaster()
+	-- Read the db option for master.  Is it set?
+	if EMA.db.master:trim() == "" then
+		-- No, set it to self.
+		SetMaster( EMA.characterName )
+	end
+	-- Is the master in the member list?
+	if not IsCharacterInTeam( EMA.db.master ) then
+		-- No, set self as master.
+		SetMaster( EMA.characterName )
+	end
+end
+
+-- Remove a member from the member list.
+local function RemoveMember( importName )
+	local singleName, singleRealm = strsplit( "-" , importName, 2 )
+	local characterName = nil
+	local name = EMAUtilities:Capitalise( singleName )
+
+	if singleRealm ~= nil then
+		characterName = name.."-"..singleRealm
+	else
+		characterName = name
+	end
+	-- Is character in team?
+	if IsCharacterInTeam( characterName ) == true and characterName ~= EMA.characterName then
+		-- Remove character from list.
+	local characterPosition = EMAApi.GetPositionForCharacterName( characterName )
+	-- REMOVES THE CHAR!
+	EMA.db.newTeamList[characterName] = nil
+		-- If any character had an order greater than this character's order, then shift their order down by one.
+		for checkCharacterName, info in pairs (EMA.db.newTeamList) do
+			for _, charInfo in pairs (info) do
+				if charInfo.order > characterPosition then
+					charInfo.order = charInfo.order - 1
+				end
+			end
+		end
+		-- Send a message to any listeners that this character has been removed.
+		EMA:SendMessage( EMA.MESSAGE_TEAM_CHARACTER_REMOVED, characterName )
+		-- Make sure EMA character is a member.
+		ConfirmCharacterIsInTeam()
+		-- Make sure there is a master, if none, set this character.
+		ConfirmThereIsAMaster()
+		-- Refresh the settings.
+		EMA:SettingsRefresh()
+		-- Resets to Top of list!
+		if EMA.settingsControl.teamListHighlightRow > 1 then
+			EMA:SettingsTeamListRowClick( EMA.settingsControl.teamListHighlightRow - 1 , 1 )
+		else
+			EMA:SettingsTeamListRowClick( 1 , 1 )
+		end
+	else
+		EMA:Print("[PH] CAN NOT REMOVE SELF")
+	end
+end
+
+-- Provides a GUI for a user to confirm removing selected members from the member list.
+function EMA:RemoveMemberGUI()
+	local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+	RemoveMember( characterName )
+	EMA:SettingsTeamListScrollRefresh()
+	EMA:SettingsGroupListScrollRefresh()
+	--EMA:Print("count", EMA.settingsControl.teamListHighlightRow)
+	--EMA:SettingsTeamListRowClick( EMA.settingsControl.teamListHighlightRow - 1 , 1 )
+end
+
+
+-- Remove member from the command line.
+function EMA:RemoveMemberCommand( info, parameters )
+	local characterName = EMAUtilities:Capitalise(parameters)
+	if info ~= nil then
+		if characterName ~= nil and characterName:trim() ~= "" and characterName:len() > 1 then
+			-- Remove the character.
+			RemoveMember( characterName )
+		end
+	end
+end
+
+local function RemoveAllMembersFromTeam()
+	for characterName, position in EMAApi.TeamList() do
+		RemoveMember( characterName )
+	end
+end
+
+-- Remove all members from the team list via command line.
+function EMA:DoRemoveAllMembersFromTeam( info, parameters )
+	RemoveAllMembersFromTeam()
+end
+
+function EMA:CommandIAmMaster( info, parameters )
+	local tag = parameters
+	local target = EMA.characterName
+	if tag ~= nil and tag:trim() ~= "" then
+		EMA:EMASendCommandToTeam( EMA.COMMAND_SET_MASTER, target, tag )
+	else
+		EMA:EMASendCommandToTeam( EMA.COMMAND_SET_MASTER, target, "all" )
+		SetMaster( target )
+	end
+end
+
+function EMA:CommandSetMaster( info, parameters )
+	local target, tag = strsplit( " ", parameters )
+	if tag ~= nil and tag:trim() ~= "" then
+		EMA:EMASendCommandToTeam( EMA.COMMAND_SET_MASTER, target, tag )
+	else
+		EMA:EMASendCommandToTeam( EMA.COMMAND_SET_MASTER, target, "all" )
+		SetMaster( target )
+	end
+end
+
+function EMA:ReceiveCommandSetMaster( target, tag )
+	if EMAPrivate.Tag.DoesCharacterHaveTag( EMA.characterName, tag ) then
+		SetMaster( target )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Character online status.
+-------------------------------------------------------------------------------------------------------------
+
+-- Get a character's online status..
+local function GetCharacterOnlineStatus( characterName )
+	local online = nil
+	for name, info in pairs (EMA.db.newTeamList) do
+		for _, charInfo in pairs (info) do
+			if characterName == name then
+				online = charInfo.online
+			end
+		end
+	end
+	return online
+end
+
+-- Set a character's online status.
+local function SetCharacterOnlineStatus( characterName, isOnline )
+	--EMA:Print("setting", characterName, "to be", isOnline )
+	for name, info in pairs (EMA.db.newTeamList) do
+		for _, charInfo in pairs (info) do
+			if characterName == name then
+				--EMA:Print("Set", characterName, isOnline, charInfo.online )
+				charInfo.online = isOnline
+			end
+		end
+	end
+end
+
+local function SetTeamStatusToOffline()
+	for characterName, characterPosition in EMAApi.TeamList() do
+		SetCharacterOnlineStatus( characterName, false )
+		EMA:SendMessage( EMA.MESSAGE_CHARACTER_OFFLINE )
+		EMA:SettingsTeamListScrollRefresh()
+	end
+end
+
+local function SetTeamOnline()
+	-- Set all characters online status to false.
+	for characterName, characterPosition in EMAApi.TeamList() do
+		SetCharacterOnlineStatus( characterName, true )
+		EMA:SendMessage( EMA.MESSAGE_CHARACTER_ONLINE )
+		EMA:SettingsTeamListScrollRefresh()
+		--EMA:SettingsGroupListScrollRefresh()
+	end
+end
+
+--Set character Offline.
+local function setOffline( characterName )
+	local character = EMAUtilities:AddRealmToNameIfMissing( characterName )
+	SetCharacterOnlineStatus( character, false )
+	EMA:SendMessage( EMA.MESSAGE_CHARACTER_OFFLINE )
+	EMA:SettingsTeamListScrollRefresh()
+	--EMA:SettingsGroupListScrollRefresh()
+end
+
+--Set character OnLine.
+local function setOnline( characterName )
+	local character = EMAUtilities:AddRealmToNameIfMissing( characterName )
+	SetCharacterOnlineStatus( character, true )
+	EMA:SendMessage( EMA.MESSAGE_CHARACTER_ONLINE )
+	EMA:SettingsTeamListScrollRefresh()
+	--EMA:SettingsGroupListScrollRefresh()
+end
+
+function EMA.ReceivesetOffline( characterName )
+	--EMA:Print("command", characterName )
+	setOffline( characterName, false )
+	EMA:SettingsRefresh()
+end
+
+function EMA.ReceivesetOnline( characterName )
+	--EMA:Print("command", characterName )
+	setOnline( characterName, false )
+	EMA:SettingsRefresh()
+end
+
+function EMA:SetAllMembersOffline()
+	SetTeamStatusToOffline()
+end
+
+function EMA:SetAllMembersOnline()
+	SetTeamOnline()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Character team list ordering.
+-------------------------------------------------------------------------------------------------------------
+
+local function SortTeamListOrdered( characterA, characterB )
+	local positionA = GetPositionForCharacterName( characterA )
+	local positionB = GetPositionForCharacterName( characterB )
+	return positionA < positionB
+end
+
+-- Return all characters ordered.
+local function TeamListOrdered()
+	EMAUtilities:ClearTable( EMA.orderedCharacters )
+	for characterName, characterPosition in EMAApi.TeamList() do
+		table.insert( EMA.orderedCharacters, characterName )
+	end
+	table.sort( EMA.orderedCharacters, SortTeamListOrdered )
+	return ipairs( EMA.orderedCharacters )
+end
+
+-- Return all characters ordered online.
+local function TeamListOrderedOnline()
+	EMAUtilities:ClearTable( EMA.orderedCharactersOnline )
+	for characterName, characterPosition in EMAApi.TeamList() do
+		if EMAApi.GetCharacterOnlineStatus( characterName ) == true then
+			table.insert( EMA.orderedCharactersOnline, characterName )
+		end
+	end
+	table.sort( EMA.orderedCharactersOnline, SortTeamListOrdered )
+	return ipairs( EMA.orderedCharactersOnline )
+end
+-------------------------------------------------------------------------------------------------------------
+-- Party.
+-------------------------------------------------------------------------------------------------------------
+
+-- Invite team to party.
+
+function EMA.DoTeamPartyInvite()
+	InviteUnit( EMA.inviteList[EMA.currentInviteCount] )
+	EMA.currentInviteCount = EMA.currentInviteCount + 1
+	if EMA.currentInviteCount < EMA.inviteCount then
+		--if GetTeamListMaximumOrderOnline() > 5 and EMA.db.inviteConvertToRaid == true then
+		if EMA.inviteCount > 4 and EMA.db.inviteConvertToRaid == true then
+			if EMA.db.inviteSetAllAssistant == true then
+				ConvertToRaid()
+				SetEveryoneIsAssistant(true)
+			else
+				ConvertToRaid()
+			end
+		end
+		EMA:ScheduleTimer( "DoTeamPartyInvite", 0.5 )
+	end
+end
+
+
+function EMA:InviteTeamToParty( info, tag )
+	-- Iterate each enabled member and invite them to a group.
+	if tag == nil or tag == "" then
+		tag = "all"
+	end
+	if EMAApi.DoesGroupExist(tag) == true then
+		if EMAApi.IsCharacterInGroup( EMA.characterName, tag ) == false then
+			--EMA:Print("IDONOTHAVETAG", tag)
+			for index, characterName in TeamListOrderedOnline() do
+				--EMA:Print("NextChartohavetag", tag, characterName )
+				if EMAApi.IsCharacterInGroup( characterName, tag ) then
+					--EMA:Print("i have tag", tag, characterName )
+					EMA:EMASendCommandToTeam( EMA.COMMAND_TAG_PARTY, characterName, tag )
+					break
+				end
+			end
+			return
+		else
+			EMA.inviteList = {}
+			EMA.inviteCount = 0
+			for index, characterName in TeamListOrderedOnline() do
+				if EMAApi.IsCharacterInGroup( characterName, tag ) == true then
+					--EMA:Print("HasTag", characterName, tag )
+					-- As long as they are not the player doing the inviting.
+					if characterName ~= EMA.characterName then
+						EMA.inviteList[EMA.inviteCount] = characterName
+						EMA.inviteCount = EMA.inviteCount + 1
+					end
+				end
+			end
+		end
+		EMA.currentInviteCount = 0
+		EMA:ScheduleTimer( "DoTeamPartyInvite", 0.5 )
+	else
+	EMA:Print (L["UNKNOWN_GROUP"]..tag )
+	end
+end
+
+function EMA:doTagParty(event, characterName, tag, ...)
+	--EMA:Print("test", characterName, tag )
+	if EMA.characterName == characterName then
+	 --EMA:Print("this msg is for me", characterName )
+		if EMAApi.IsCharacterInGroup( EMA.characterName, tag ) == true then
+			EMA:InviteTeamToParty( nil, tag)
+		else
+			return
+		end
+	 end
+end
+
+function EMA:PARTY_INVITE_REQUEST( event, inviter, ... )
+	--EMA:Print("Inviter", inviter)
+	-- Accept this invite, initially no.
+	local acceptInvite = false
+	-- Is character not in a group?
+	if not IsInGroup( "player" ) then
+		-- Accept an invite from members?
+		if EMA.db.inviteAcceptTeam == true then
+			-- If inviter found in team list, allow the invite to be accepted.
+			if IsCharacterInTeam( inviter ) then
+			acceptInvite = true
+			end
+		end
+		-- Accept an invite from friends?
+		if EMA.db.inviteAcceptFriends == true then
+			-- Iterate each friend; searching for the inviter in the friends list.
+			for friendIndex = 1, GetNumFriends() do
+				local friendName = GetFriendInfo( friendIndex )
+				-- Inviter found in friends list, allow the invite to be accepted.
+				if inviter == friendName then
+					acceptInvite = true
+					break
+				end
+			end
+		end
+		-- Accept an invite from BNET/RealD?
+		if EMA.db.inviteAcceptFriends == true and BNFeaturesEnabledAndConnected() == true then
+			-- Iterate each friend; searching for the inviter in the friends list.
+			local _, numFriends = BNGetNumFriends()
+			for bnIndex = 1, numFriends do
+				for toonIndex = 1, BNGetNumFriendGameAccounts( bnIndex ) do
+					local _, toonName, client, realmName = BNGetFriendGameAccountInfo( bnIndex, toonIndex )
+					--EMA:Print("BNFrindsTest", toonName, client, realmName, "inviter", inviter)
+					if client == "WoW" then
+						if toonName == inviter or toonName.."-"..realmName == inviter then
+							acceptInvite = true
+							break
+						end
+					end
+				end
+			end
+		end
+		-- Accept and invite from guild members?
+		if EMA.db.inviteAcceptGuild == true then
+			if UnitIsInMyGuild( inviter ) then
+				acceptInvite = true
+			end
+		end
+	end
+	-- Hide the party invite popup?
+	local hidePopup = false
+	-- Accept the group invite if allowed.
+	if acceptInvite == true then
+		AcceptGroup()
+		hidePopup = true
+	else
+		-- Otherwise decline the invite if permitted.
+		if EMA.db.inviteDeclineStrangers == true then
+			DeclineGroup()
+			hidePopup = true
+		end
+	end
+	-- Hide the popup group invitation request if accepted or declined the invite.
+	if hidePopup == true then
+		-- Make sure the invite dialog does not decline the invitation when hidden.
+		for iteratePopups = 1, STATICPOPUP_NUMDIALOGS do
+			local dialog = _G["StaticPopup"..iteratePopups]
+			if dialog.which == "PARTY_INVITE" then
+				-- Set the inviteAccepted flag to true (even if the invite was declined, as the
+				-- flag is only set to stop the dialog from declining in its OnHide event).
+				dialog.inviteAccepted = 1
+				break
+			end
+			-- Ebony Sometimes invite is from XREALM even though Your on the same realm and have joined the party. This should hide the Popup.
+			if dialog.which == "PARTY_INVITE_XREALM" then
+				-- Set the inviteAccepted flag to true (even if the invite was declined, as the
+				-- flag is only set to stop the dialog from declining in its OnHide event).
+				dialog.inviteAccepted = 1
+				break
+			end
+		end
+		StaticPopup_Hide( "PARTY_INVITE" )
+		StaticPopup_Hide( "PARTY_INVITE_XREALM" )
+	end
+end
+
+function EMA:DisbandTeamFromParty()
+	EMA:EMASendCommandToTeam( EMA.COMMAND_LEAVE_PARTY )
+end
+
+local function LeaveTheParty()
+	if IsInGroup( "player" ) then
+		LeaveParty()
+	end
+end
+
+function EMA:OnMasterChange( message, characterName )
+	--EMA:Print("test", message, characterName)
+	local playerName = EMA.characterName
+	if EMA.db.masterChangePromoteLeader == true then
+		if IsInGroup( "player" ) and UnitIsGroupLeader( "player" ) == true and GetMasterName() ~= playerName then
+			PromoteToLeader( Ambiguate( GetMasterName(), "all" ) )
+		end
+	end
+	if EMA.db.masterChangeClickToMove == true then
+		if IsCharacterTheMaster( self.characterName ) == true then
+			ConsoleExec("Autointeract 0")
+		else
+			ConsoleExec("Autointeract 1")
+		end
+	end
+end
+
+function EMA:AddIsboxerMembers()
+	if IsAddOnLoaded("Isboxer" ) then
+		for slot, characterName in EMAApi.IsboxerTeamList() do
+			EMAApi.AddMember( characterName )
+		end
+	else
+		EMA:Print(L["ISBOXER_ADDON_NOT_LOADED"])
+	end
+end
+
+-- LOOT FOR Classic
+
+local function SetPartyLoot( desiredLootOption )
+	--EMA:Print("test", desiredLootOption )
+	-- Is this character in a party and the party leader?
+	local isLeader = UnitIsGroupLeader("player")
+	if GetNumGroupMembers() > 0 and isLeader == true then
+		-- What is the current loot method?
+		local lootMethod, partyMaster, raidMaster = GetLootMethod()
+		-- Can the loot method be changed?
+		local canChangeLootMethod = false
+		-- Different loot methods?
+		if lootMethod ~= desiredLootOption then
+			-- Yes, can change loot method.
+			canChangeLootMethod = true
+		else
+			-- Same, loot methods, but master looter...
+			if desiredLootOption == EMA.PARTY_LOOT_MASTER and partyMaster ~= nil then
+				-- And is a different master looter...
+				-- If partyMaster is 0, then this player is the master looter.
+				if partyMaster == 0 and IsCharacterTheMaster( EMA.characterName ) == false then
+					-- Then, yes, can change loot method.
+					canChangeLootMethod = true
+				end
+				-- If partyMaster between 1 and 4 then that player (party1 .. party4) is the master looter.
+				if partyMaster > 0 then
+					if UnitName( "party"..partyMaster ) ~= GetMasterName() then
+						-- Then, yes, can change loot method.
+						canChangeLootMethod = true
+					end
+				end
+			end
+		end
+		-- SetLootMethod fires the PartyLeaderChanged event (need to check that loot is not being set to
+		-- the same loot method; otherwise an infinite loop occurs).
+		if canChangeLootMethod == true then
+			if desiredLootOption == EMA.PARTY_LOOT_MASTER then
+				SetLootMethod( desiredLootOption, GetMasterName(), 1 )
+			else
+				SetLootMethod( desiredLootOption )
+			end
+		end
+	end
+end
+
+function EMA:PARTY_LEADER_CHANGED( event, ... )
+	if EMA.db.lootSetAutomatically == true then
+		local isLeader = UnitIsGroupLeader("player")
+		if isLeader == true then
+			-- Is there a stranger in the group?
+			local haveStranger = false
+			if EMA.db.lootToGroupIfStrangerPresent == true then
+				local numberPartyMembers = GetNumGroupMembers()
+				for iteratePartyMembers = numberPartyMembers, 1, -1 do
+					local partyMemberName, partyMemberRealm = UnitName( "party"..iteratePartyMembers )
+					local character = EMAUtilities:AddRealmToNameIfNotNil( partyMemberName, partyMemberRealm )
+					if partyMemberName ~= nil then
+						if IsCharacterInTeam( character ) == false then
+							if EMA.db.lootToGroupFriendsAreNotStrangers == true then
+								local isAFriend = false
+								for friendIndex = 1, GetNumFriends() do
+									local friendName = GetFriendInfo( friendIndex )
+									if partyMemberName == friendName then
+										isAFriend = true
+									end
+								end
+								if isAFriend == false then
+									haveStranger = true
+								end
+							else
+								haveStranger = true
+							end
+						end
+					end
+				end
+				if haveStranger == true then
+					SetPartyLoot( EMA.PARTY_LOOT_GROUP )
+				end
+			end
+			if haveStranger == false then
+				-- Automatically set the loot to free for all?
+				if EMA.db.lootSetFreeForAll == true then
+					SetPartyLoot( EMA.PARTY_LOOT_FREEFORALL )
+				end
+				-- Automatically set the loot to master loot?
+				if EMA.db.lootSetMasterLooter == true then
+					SetPartyLoot( EMA.PARTY_LOOT_MASTER )
+				end
+			end
+		end
+	end
+	EMA:CheckSlavesOptOutOfLoot()
+end
+
+function EMA:GROUP_ROSTER_UPDATE( event, ... )
+	EMA:CheckSlavesOptOutOfLoot()
+end
+
+function EMA:CheckSlavesOptOutOfLoot()
+	-- Set opt out of loot rolls?
+	if EMA.db.lootSlavesOptOutOfLoot == true then
+		-- Only if not the master.
+		if IsCharacterTheMaster( EMA.characterName ) == false then
+			if GetOptOutOfLoot() == nil then
+				SetOptOutOfLoot( true )
+			end
+		else
+			if GetOptOutOfLoot() == 1 then
+				SetOptOutOfLoot( false )
+			end
+		end
+	else
+		if GetOptOutOfLoot() == 1 then
+			SetOptOutOfLoot( false )
+		end
+	end
+end
+
+
+
+-------------------------------------------------------------------------------------------------------------
+-- Addon initialization, enabling and disabling.
+-------------------------------------------------------------------------------------------------------------
+
+-- Initialise the module.
+function EMA:OnInitialize()
+	-- Create the settings control.
+	SettingsCreate()
+	-- Initialise the EMAModule part of this module.
+	EMA:EMAModuleInitialize( EMA.settingsControl.widgetSettings.frame )
+	-- Populate the settings.
+	EMA:SettingsRefresh()
+	-- Initialise the popup dialogs.
+	InitializePopupDialogs()
+	-- Make sure this character is a member, add and enable if not on the list.
+	ConfirmCharacterIsInTeam()
+	-- Make sure there is a master, if none, set this character.
+	ConfirmThereIsAMaster()
+	-- Set team members online status to not connected. we do not want to do this on start-up!
+	--SetTeamStatusToOffline()
+	SetTeamOnline()
+	-- Adds DefaultGroups to GUI
+	EMA.characterGroupList = {}
+	-- Key bindings.
+	EMATeamSecureButtonInvite = CreateFrame( "CheckButton", "EMATeamSecureButtonInvite", nil, "SecureActionButtonTemplate" )
+	EMATeamSecureButtonInvite:SetAttribute( "type", "macro" )
+	EMATeamSecureButtonInvite:SetAttribute( "macrotext", "/ema-team invite" )
+	EMATeamSecureButtonInvite:Hide()
+	EMATeamSecureButtonDisband = CreateFrame( "CheckButton", "EMATeamSecureButtonDisband", nil, "SecureActionButtonTemplate" )
+	EMATeamSecureButtonDisband:SetAttribute( "type", "macro" )
+	EMATeamSecureButtonDisband:SetAttribute( "macrotext", "/ema-team disband" )
+	EMATeamSecureButtonDisband:Hide()
+	EMATeamSecureButtonMaster = CreateFrame( "CheckButton", "EMATeamSecureButtonMaster", nil, "SecureActionButtonTemplate" )
+	EMATeamSecureButtonMaster:SetAttribute( "type", "macro" )
+	EMATeamSecureButtonMaster:SetAttribute( "macrotext", "/ema-team iammaster" )
+	EMATeamSecureButtonMaster:Hide()
+	--Sets The class of the char.
+	--	setClass()
+
+end
+
+-- Called when the addon is enabled.
+function EMA:OnEnable()
+	EMA:RegisterEvent( "PARTY_INVITE_REQUEST" )
+	EMA:RegisterEvent( "PARTY_LEADER_CHANGED" )
+	EMA:RegisterEvent( "GROUP_ROSTER_UPDATE" )
+	EMA:RegisterMessage( EMA.MESSAGE_TEAM_MASTER_CHANGED, "OnMasterChange" )
+	-- Kickstart the settings team list scroll frame.
+	EMA:SettingsTeamListScrollRefresh()
+	EMA:RegisterEvent( "PLAYER_ENTERING_WORLD" )
+	-- Initialise key bindings.
+	EMA.keyBindingFrame = CreateFrame( "Frame", nil, UIParent )
+	EMA:RegisterEvent( "UPDATE_BINDINGS" )
+	EMA:UPDATE_BINDINGS()
+	-- Update DropDownList
+	refreshDropDownList()
+end
+
+-- Called when the addon is disabled.
+function EMA:OnDisable()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Populate.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:BeforeEMAProfileChanged()
+end
+
+function EMA:OnEMAProfileChanged()
+	-- Refresh the settings.
+	EMA:SettingsRefresh()
+	-- Make sure this character is a member, add and enable if not on the list.
+	ConfirmCharacterIsInTeam()
+	-- Make sure there is a master, if none, set this character.
+	ConfirmThereIsAMaster()
+	-- Update the settings team list.
+	EMA:SettingsTeamListScrollRefresh()
+	--EMA:SettingsGroupListScrollRefresh()
+	-- Send team order changed and team master changed messages.
+	EMA:SendMessage( EMA.MESSAGE_TEAM_ORDER_CHANGED )
+	EMA:SendMessage( EMA.MESSAGE_TEAM_MASTER_CHANGED )
+end
+
+function EMA:SettingsRefresh()
+	-- Team/Group Control
+	local test = " "
+	-- Master Control.
+	EMA.settingsControl.masterControlCheckBoxMasterChange:SetValue( EMA.db.masterChangePromoteLeader )
+	EMA.settingsControl.masterControlCheckBoxMasterChangeClickToMove:SetValue( EMA.db.masterChangeClickToMove )
+	-- Party Invitiation Control.
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptMembers:SetValue( EMA.db.inviteAcceptTeam )
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptFriends:SetValue( EMA.db.inviteAcceptFriends )
+	EMA.settingsControl.partyInviteControlCheckBoxAcceptGuild:SetValue( EMA.db.inviteAcceptGuild )
+	EMA.settingsControl.partyInviteControlCheckBoxDeclineStrangers:SetValue( EMA.db.inviteDeclineStrangers )
+	EMA.settingsControl.partyInviteControlCheckBoxConvertToRaid:SetValue( EMA.db.inviteConvertToRaid )
+	EMA.settingsControl.partyInviteControlCheckBoxSetAllAssist:SetValue( EMA.db.inviteSetAllAssistant )
+	-- Party Loot Control.
+	EMA.settingsControl.partyLootControlCheckBoxSetLootMethod:SetValue( EMA.db.lootSetAutomatically )
+	EMA.settingsControl.partyLootControlCheckBoxSetFFA:SetValue( EMA.db.lootSetFreeForAll )
+	EMA.settingsControl.partyLootControlCheckBoxSetMasterLooter:SetValue( EMA.db.lootSetMasterLooter )
+	EMA.settingsControl.partyLootControlCheckBoxStrangerToGroup:SetValue( EMA.db.lootToGroupIfStrangerPresent )
+	EMA.settingsControl.partyLootControlCheckBoxFriendsNotStrangers:SetValue( EMA.db.lootToGroupFriendsAreNotStrangers )
+	EMA.settingsControl.partyLootControlCheckBoxSetOptOutOfLoot:SetValue( EMA.db.lootSlavesOptOutOfLoot )
+	-- Ensure correct state.
+	EMA.settingsControl.partyInviteControlCheckBoxSetAllAssist:SetDisabled (not EMA.db.inviteConvertToRaid )
+	-- Update the settings team list.
+	EMA:SettingsTeamListScrollRefresh()
+	-- Check the opt out of loot settings.
+	--EMA:CheckMinionsOptOutOfLoot()
+end
+
+-- Settings received.
+function EMA:EMAOnSettingsReceived( characterName, settings )
+	if characterName ~= EMA.characterName then
+	-- Update the settings.
+		EMA.db.newTeamList = EMAUtilities:CopyTable( settings.newTeamList )
+		EMA.db.masterChangePromoteLeader = settings.masterChangePromoteLeader
+		EMA.db.inviteAcceptTeam = settings.inviteAcceptTeam
+		EMA.db.inviteAcceptFriends = settings.inviteAcceptFriends
+		EMA.db.inviteAcceptGuild = settings.inviteAcceptGuild
+		EMA.db.inviteDeclineStrangers = settings.inviteDeclineStrangers
+		EMA.db.inviteConvertToRaid = settings.inviteConvertToRaid
+		EMA.db.inviteSetAllAssistant = settings.inviteSetAllAssistant
+		EMA.db.masterChangeClickToMove = settings.masterChangeClickToMove
+		EMA.db.lootSetAutomatically = settings.lootSetAutomatically
+		EMA.db.lootSetFreeForAll = settings.lootSetFreeForAll
+		EMA.db.lootSetMasterLooter = settings.lootSetMasterLooter
+		EMA.db.lootSlavesOptOutOfLoot = settings.lootSlavesOptOutOfLoot
+		EMA.db.master = settings.master
+		SetMaster( settings.master )
+		-- Refresh the settings.
+		--EMA:SettingsRefresh()
+		-- Tell the player.
+		EMA:Print( L["SETTINGS_RECEIVED_FROM_A"]( characterName ) )
+	end
+end
+
+function EMA:PLAYER_ENTERING_WORLD(event, ...)
+	-- trying this
+	-- Click the first row in the team list table to populate the tag list table.
+	EMA:SettingsTeamListRowClick( 1, 1 )
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Settings Callbacks.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:SettingsTeamListScrollRefresh()
+	FauxScrollFrame_Update(
+		EMA.settingsControl.teamList.listScrollFrame,
+		GetTeamListMaximumOrder(),
+		EMA.settingsControl.teamList.rowsToDisplay,
+		EMA.settingsControl.teamList.rowHeight
+	)
+	EMA.settingsControl.teamListOffset = FauxScrollFrame_GetOffset( EMA.settingsControl.teamList.listScrollFrame )
+	for iterateDisplayRows = 1, EMA.settingsControl.teamList.rowsToDisplay do
+		-- Reset.
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[1].textString:SetText( "" )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[2].textString:SetText( "" )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetText( "" )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[2].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.teamList.rows[iterateDisplayRows].highlight:SetColorTexture( 0.0, 0.0, 0.0, 0.0 )
+		-- Get data.
+		local dataRowNumber = iterateDisplayRows + EMA.settingsControl.teamListOffset
+		if dataRowNumber <= GetTeamListMaximumOrder() then
+			-- Put character name and type into columns.
+			local characterName = GetCharacterNameAtOrderPosition( dataRowNumber )
+
+		--local class = EMA.db.characterClass[characterName]
+			--EMA:Print("Test", class)
+			-- Set Class Color
+			local class, color = GetClass( characterName )
+			if color ~= nil then
+				EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( color.r, color.g, color.b, 1.0 )
+			end
+			local isMaster = false
+			local characterType = L["MINION"]
+			if IsCharacterTheMaster( characterName ) == true then
+				characterType = L["MASTER"]
+				isMaster = true
+			end
+			local displayCharacterName , displayCharacterRleam = strsplit( "-", characterName, 2 )
+
+			local isOnline = GetCharacterOnlineStatus( characterName )
+			local displayOnline = nil
+			if isOnline == false then
+				displayOnline = L["OFFLINE"]
+				EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetTextColor( 1.0, 0, 0, 1.0 )
+			else
+				displayOnline = L["ONLINE"]
+				EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetTextColor( 0, 1.0, 0, 1.0 )
+			end
+
+			-- Master is a yellow colour.
+
+			if isMaster == true then
+				local icon = "Interface\\GroupFrame\\UI-Group-LeaderIcon"
+				displayCharacterName = strconcat(" |T"..icon..":20|t", L[" "]..displayCharacterName)
+			--	EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetTextColor( 1.0, 0.96, 0.41, 1.0 )
+			end
+			local RealmLinked = EMAUtilities:CheckIsFromMyRealm( characterName )
+			-- Set Realms not linked Red
+			if RealmLinked == false then
+				displayCharacterRleam = displayCharacterRleam..L[" "]..L["NOT_LINKED"]
+				EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[2].textString:SetTextColor( 1.0, 0, 0, 1.0 )
+			end
+
+			EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[1].textString:SetText( displayCharacterName )
+			EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[2].textString:SetText( displayCharacterRleam )
+			EMA.settingsControl.teamList.rows[iterateDisplayRows].columns[3].textString:SetText( displayOnline )
+			-- Highlight the selected row.
+			if dataRowNumber == EMA.settingsControl.teamListHighlightRow then
+				EMA.settingsControl.teamList.rows[iterateDisplayRows].highlight:SetColorTexture( 1.0, 1.0, 0.0, 0.5 )
+			end
+		end
+	end
+end
+
+local function DisplayGroupsForCharacterInGroupsList( characterName )
+	if characterName == nil then return end
+	--EMA:Print("test", characterName )
+	EMA.characterGroupList = EMAApi.GetGroupListForCharacter( characterName )
+	table.sort( EMA.characterGroupList )
+	EMA:SettingsGroupListScrollRefresh()
+	--end
+end
+
+local function GetGroupAtPosition( position )
+	return EMA.characterGroupList[position]
+
+end
+
+local function GetTagListMaxPosition()
+	return #EMA.characterGroupList
+end
+
+function EMA:SettingsTeamListRowClick( rowNumber, columnNumber )
+	if EMA.settingsControl.teamListOffset + rowNumber <= GetTeamListMaximumOrder() then
+		EMA.settingsControl.teamListHighlightRow = EMA.settingsControl.teamListOffset + rowNumber
+		EMA:SettingsTeamListScrollRefresh()
+		-- Group
+		EMA.settingsControl.groupListHighlightRow = 1
+		local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+		DisplayGroupsForCharacterInGroupsList( characterName )
+		if columnNumber == 3 then
+			local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+			local onLine = GetCharacterOnlineStatus(characterName)
+			if onLine == true and characterName ~= EMA.characterName then
+				setOffline( characterName )
+			else
+				setOnline( characterName )
+			end
+		end
+	end
+end
+
+function EMA:SettingsGroupListScrollRefresh()
+	FauxScrollFrame_Update(
+		EMA.settingsControl.groupList.listScrollFrame,
+		--EMAPrivate.Tag.GetTagListMaxPosition(),
+		EMAApi.CharacterMaxGroups(),
+		EMA.settingsControl.groupList.rowsToDisplay,
+		EMA.settingsControl.groupList.rowHeight
+	)
+	EMA.settingsControl.groupListOffset = FauxScrollFrame_GetOffset( EMA.settingsControl.groupList.listScrollFrame )
+	for iterateDisplayRows = 1, EMA.settingsControl.groupList.rowsToDisplay do
+
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetText( "" )
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 1.0, 1.0, 1.0 )
+		EMA.settingsControl.groupList.rows[iterateDisplayRows].highlight:SetColorTexture( 0.0, 0.0, 0.0, 0.0 )
+		local dataRowNumber = iterateDisplayRows + EMA.settingsControl.groupListOffset
+		if dataRowNumber <= EMAApi.CharacterMaxGroups() then
+		--local characterName = EMAApi.GetGroupListForCharacter --EMA.CharGroupListName
+		--local group = GetGroupAtPosition(characterName,dataRowNumber)
+		local group = GetGroupAtPosition( dataRowNumber )
+		local groupName = EMAUtilities:Capitalise( group )
+		--local group = EMAApi.GetGroupAtPosition( dataRowNumber )
+			EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetText( groupName )
+			--EMA:Print("test", dataRowNumber, group, characterName )
+			local systemGroup = EMAApi.IsASystemGroup( group )
+			if systemGroup == true then
+				EMA.settingsControl.groupList.rows[iterateDisplayRows].columns[1].textString:SetTextColor( 1.0, 0.96, 0.41, 1.0 )
+			end
+			if dataRowNumber == EMA.settingsControl.groupListHighlightRow then
+				EMA.settingsControl.groupList.rows[iterateDisplayRows].highlight:SetColorTexture( 1.0, 1.0, 0.0, 0.5 )
+			end
+		end
+	end
+
+end
+
+function EMA:SettingsGroupListRowClick( rowNumber, columnNumber )
+	if EMA.settingsControl.groupListOffset + rowNumber <= GetTagListMaxPosition() then
+		EMA.settingsControl.groupListHighlightRow = EMA.settingsControl.groupListOffset + rowNumber
+		EMA:SettingsGroupListScrollRefresh()
+	end
+end
+
+-- For Api Update For anywhere you add a Group. ( mosty Tag.lua )
+local function RefreshGroupList()
+	EMA:SettingsGroupListScrollRefresh()
+end
+
+function EMA:TeamListDropDownList(event, value )
+	-- if nil or the blank group then don't get Name.
+	if value == " " or value == nil then
+		return
+	end
+	local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+	local groupName = EMAUtilities:Lowercase( value )
+	--EMA:Print("test", characterName, groupName )
+	-- We Have a group and characterName Lets Add it to the groupList
+	EMAApi.AddCharacterToGroup( characterName, groupName )
+	-- Reset the groupList Back to "Nothing"
+	EMA.settingsControl.teamListDropDownList:SetValue( " " )
+	-- update Lists
+	EMA:SettingsRefresh()
+	EMA:SettingsGroupListScrollRefresh()
+end
+
+function EMA.SettingsRemoveGroupClick(event, value )
+	local tag = GetGroupAtPosition( EMA.settingsControl.groupListHighlightRow )
+	local systemGroup = EMAApi.IsASystemGroup( tag )
+	local groupName = EMAUtilities:Lowercase( tag )
+	local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+	local systemGroup = EMAApi.IsASystemGroup( tag )
+	-- Remove From Tag List
+	if systemGroup == false then
+		EMAApi.RemoveGroupFromCharacter( characterName, groupName )
+	else
+		--TODO: Update
+		EMA:Print("[PH] CAN NOT REMOVE FORM THIS GROUP!")
+	end
+	-- update Lists
+	EMA:SettingsRefresh()
+	EMA:SettingsGroupListScrollRefresh()
+end
+
+function EMA:SettingsPushSettingsClick( event )
+	EMA:EMASendSettings()
+	--We Needs to Update The TeamGroup List as well.
+	EMAApi.PushGroupSettings()
+end
+
+function EMA:SettingsMoveUpClick( event )
+	if EMA.settingsControl.teamListHighlightRow > 1 then
+		TeamListSwapCharacterPositions( EMA.settingsControl.teamListHighlightRow, EMA.settingsControl.teamListHighlightRow - 1 )
+		EMA.settingsControl.teamListHighlightRow = EMA.settingsControl.teamListHighlightRow - 1
+		if EMA.settingsControl.teamListHighlightRow <= EMA.settingsControl.teamListOffset then
+			EMAHelperSettings:SetFauxScrollFramePosition(
+				EMA.settingsControl.teamList.listScrollFrame,
+				EMA.settingsControl.teamListHighlightRow - 1,
+				GetTeamListMaximumOrder(),
+				EMA.settingsControl.teamList.rowHeight
+			)
+		end
+		EMA:SettingsTeamListScrollRefresh()
+		--EMA:SettingsGroupListScrollRefresh()
+		EMA:SendMessage( EMA.MESSAGE_TEAM_ORDER_CHANGED )
+	end
+end
+
+function EMA:SettingsMoveDownClick( event )
+	if EMA.settingsControl.teamListHighlightRow < GetTeamListMaximumOrder() then
+		TeamListSwapCharacterPositions( EMA.settingsControl.teamListHighlightRow, EMA.settingsControl.teamListHighlightRow + 1 )
+		EMA.settingsControl.teamListHighlightRow = EMA.settingsControl.teamListHighlightRow + 1
+		if EMA.settingsControl.teamListHighlightRow > ( EMA.settingsControl.teamListOffset + EMA.settingsControl.teamList.rowsToDisplay ) then
+			EMAHelperSettings:SetFauxScrollFramePosition(
+				EMA.settingsControl.teamList.listScrollFrame,
+				EMA.settingsControl.teamListHighlightRow + 1,
+				GetTeamListMaximumOrder(),
+				EMA.settingsControl.teamList.rowHeight
+			)
+		end
+		EMA:SettingsTeamListScrollRefresh()
+		--EMA:SettingsGroupListScrollRefresh()
+		EMA:SendMessage( EMA.MESSAGE_TEAM_ORDER_CHANGED )
+	end
+end
+
+function EMA:SettingsAddClick( event )
+	StaticPopup_Show( "EMATEAM_ASK_CHARACTER_NAME" )
+end
+
+function EMA:SettingsRemoveClick( event )
+	local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+	StaticPopup_Show( "EMATEAM_CONFIRM_REMOVE_CHARACTER", characterName )
+end
+
+function EMA.SettingsAddPartyClick( event )
+	EMA:AddPartyMembers()
+end
+
+function EMA:SettingsAddIsboxerListClick( event )
+	EMA:AddIsboxerMembers()
+end
+
+function EMA:SettingsInviteClick( event )
+	EMA:InviteTeamToParty(nil)
+end
+
+function EMA:SettingsDisbandClick( event )
+	EMA:DisbandTeamFromParty()
+end
+
+function EMA:SettingsSetMasterClick( event )
+	local characterName = GetCharacterNameAtOrderPosition( EMA.settingsControl.teamListHighlightRow )
+	EMA:EMASendCommandToTeam( EMA.COMMAND_SET_MASTER, characterName, "all" )
+	SetMaster( characterName )
+	EMA:SettingsTeamListScrollRefresh()
+end
+
+function EMA:SettingsMasterChangeToggle( event, checked )
+	EMA.db.masterChangePromoteLeader = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsMasterChangeClickToMoveToggle( event, checked )
+	EMA.db.masterChangeClickToMove = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsAcceptInviteMembersToggle( event, checked )
+	EMA.db.inviteAcceptTeam = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsAcceptInviteFriendsToggle( event, checked )
+	EMA.db.inviteAcceptFriends = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsAcceptInviteGuildToggle( event, checked )
+	EMA.db.inviteAcceptGuild = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsDeclineInviteStrangersToggle( event, checked )
+	EMA.db.inviteDeclineStrangers = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsinviteConvertToRaidToggle( event, checked )
+	EMA.db.inviteConvertToRaid = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsinviteSetAllAssistToggle( event, checked )
+	EMA.db.inviteSetAllAssistant = checked
+end
+
+function EMA:SettingsSetLootMethodToggle( event, checked )
+	EMA.db.lootSetAutomatically = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsSetFFALootToggle( event, checked )
+	EMA.db.lootSetFreeForAll = checked
+	EMA.db.lootSetMasterLooter = not checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsSetMasterLooterToggle( event, checked )
+	EMA.db.lootSetMasterLooter = checked
+	EMA.db.lootSetFreeForAll = not checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsSetStrangerToGroup( event, checked )
+	EMA.db.lootToGroupIfStrangerPresent = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsSetFriendsNotStrangers( event, checked )
+	EMA.db.lootToGroupFriendsAreNotStrangers = checked
+	EMA:SettingsRefresh()
+end
+
+function EMA:SettingsSetSlavesOptOutToggle( event, checked )
+	EMA.db.lootSlavesOptOutOfLoot = checked
+	EMA:SettingsRefresh()
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Key bindings.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:UPDATE_BINDINGS()
+	if InCombatLockdown() then
+		return
+	end
+	ClearOverrideBindings( EMA.keyBindingFrame )
+	local key1, key2 = GetBindingKey( "TEAMINVITE" )
+	if key1 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key1, "EMATeamSecureButtonInvite" )
+	end
+	if key2 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key2, "EMATeamSecureButtonInvite" )
+	end
+	local key1, key2 = GetBindingKey( "TEAMDISBAND" )
+	if key1 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key1, "EMATeamSecureButtonDisband" )
+	end
+	if key2 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key2, "EMATeamSecureButtonDisband" )
+	end
+	local key1, key2 = GetBindingKey( "TEAMMASTER" )
+	if key1 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key1, "EMATeamSecureButtonMaster" )
+	end
+	if key2 then
+		SetOverrideBindingClick( EMA.keyBindingFrame, false, key2, "EMATeamSecureButtonMaster" )
+	end
+end
+
+-------------------------------------------------------------------------------------------------------------
+-- Commands.
+-------------------------------------------------------------------------------------------------------------
+
+function EMA:EMAOnCommandReceived( sender, commandName, ... )
+	if commandName == EMA.COMMAND_LEAVE_PARTY then
+		if IsCharacterInTeam( sender ) == true then
+			LeaveTheParty()
+		end
+	end
+	if commandName == EMA.COMMAND_SET_MASTER then
+		if IsCharacterInTeam( sender ) == true then
+			EMA:ReceiveCommandSetMaster( ... )
+		end
+	end
+	--Ebony
+	if commandName == EMA.COMMAND_SET_OFFLINE then
+		if IsCharacterInTeam( sender ) == true then
+			EMA.ReceivesetOffline( ... )
+		end
+	end
+	if commandName == EMA.COMMAND_SET_ONLINE then
+		if IsCharacterInTeam( sender ) == true then
+			EMA.ReceivesetOnline( ... )
+		end
+	end
+	if commandName == EMA.COMMAND_TAG_PARTY then
+		if IsCharacterInTeam( sender ) == true then
+			EMA.doTagParty( characterName, tag, ... )
+		end
+	end
+end
+
+-- Functions available from EMA Team for other EMA internal objects.
+EMAPrivate.Team.MESSAGE_TEAM_MASTER_CHANGED = EMA.MESSAGE_TEAM_MASTER_CHANGED
+EMAPrivate.Team.MESSAGE_TEAM_ORDER_CHANGED = EMA.MESSAGE_TEAM_ORDER_CHANGED
+EMAPrivate.Team.MESSAGE_TEAM_CHARACTER_ADDED = EMA.MESSAGE_TEAM_CHARACTER_ADDED
+EMAPrivate.Team.MESSAGE_TEAM_CHARACTER_REMOVED = EMA.MESSAGE_TEAM_CHARACTER_REMOVED
+EMAPrivate.Team.TeamList = TeamList
+EMAPrivate.Team.IsCharacterInTeam = IsCharacterInTeam
+EMAPrivate.Team.IsCharacterTheMaster = IsCharacterTheMaster
+EMAPrivate.Team.GetMasterName = GetMasterName
+EMAPrivate.Team.SetTeamStatusToOffline = SetTeamStatusToOffline
+EMAPrivate.Team.GetCharacterOnlineStatus = GetCharacterOnlineStatus
+EMAPrivate.Team.SetTeamOnline = SetTeamOnline
+EMAPrivate.Team.GetCharacterNameAtOrderPosition = GetCharacterNameAtOrderPosition
+EMAPrivate.Team.GetTeamListMaximumOrder = GetTeamListMaximumOrder
+EMAPrivate.Team.RemoveAllMembersFromTeam = RemoveAllMembersFromTeam
+EMAPrivate.Team.setOffline = setOffline
+EMAPrivate.Team.setOnline = setOline
+EMAPrivate.Team.RefreshGroupList = RefreshGroupList
+
+-- Functions available for other addons.
+EMAApi.MESSAGE_TEAM_MASTER_CHANGED = EMA.MESSAGE_TEAM_MASTER_CHANGED
+EMAApi.MESSAGE_TEAM_ORDER_CHANGED = EMA.MESSAGE_TEAM_ORDER_CHANGED
+EMAApi.MESSAGE_TEAM_CHARACTER_ADDED = EMA.MESSAGE_TEAM_CHARACTER_ADDED
+EMAApi.MESSAGE_TEAM_CHARACTER_REMOVED = EMA.MESSAGE_TEAM_CHARACTER_REMOVED
+EMAApi.IsCharacterInTeam = IsCharacterInTeam
+EMAApi.IsCharacterTheMaster = IsCharacterTheMaster
+EMAApi.GetMasterName = GetMasterName
+EMAApi.TeamList = TeamList
+EMAApi.FullTeamList = FullTeamList
+EMAApi.Offline = Offline
+EMAApi.TeamListOrdered = TeamListOrdered
+EMAApi.GetCharacterNameAtOrderPosition = GetCharacterNameAtOrderPosition
+EMAApi.GetPositionForCharacterName = GetPositionForCharacterName
+EMAApi.GetTeamListMaximumOrder = GetTeamListMaximumOrder
+EMAApi.GetCharacterOnlineStatus = GetCharacterOnlineStatus
+EMAApi.RemoveAllMembersFromTeam = RemoveAllMembersFromTeam
+EMAApi.MESSAGE_CHARACTER_ONLINE = EMA.MESSAGE_CHARACTER_ONLINE
+EMAApi.MESSAGE_CHARACTER_OFFLINE = EMA.MESSAGE_CHARACTER_OFFLINE
+EMAApi.setOffline = setOffline
+EMAApi.setOnline = setOnline
+EMAApi.GetTeamListMaximumOrderOnline = GetTeamListMaximumOrderOnline
+EMAApi.TeamListOrderedOnline = TeamListOrderedOnline
+EMAApi.GetPositionForCharacterNameOnline = GetPositionForCharacterNameOnline
+EMAApi.GetClass = GetClass
+EMAApi.AddMember = AddMember
+EMAApi.RemoveMember = RemoveMember
+EMAApi.CommandIAmMaster = EMA.CommandIAmMaster
+--EMAApi.SetClass = setClass
+EMAApi.GroupAreaList = EMA.GroupAreaList
+EMAApi.refreshDropDownList = refreshDropDownList
diff --git a/EMA-Classic.toc b/EMA-Classic.toc
index d1fb7e1..26051f5 100644
--- a/EMA-Classic.toc
+++ b/EMA-Classic.toc
@@ -2,7 +2,7 @@
 ## Title: EMA-Classic
 ## Notes: Ebony's MultiBoxing Assistant Classic
 ## Author: Jennifer Calladine 'Ebony'
-## Version: v1.13.2-Release-v0.3(121016)
+## Version: v1.13.2-Release-v0.3(121017)
 ## SavedVariables: CoreProfileDB, CommunicationsProfileDB, TeamProfileDB, TagProfileDB, MessageProfileDB, CurrProfileDB, DisplayTeamProfileDB, FollowProfileDB, GuildProfileDB, InteractionProfileDB, ItemUseProfileDB, PurchaseProfileDB, QuestProfileDB,  QuestWatcherProfileDB, SellProfileDB, TalkProfileDB, ToonProfileDB, TradeProfileDB, MailProfileDB, ISBoxerProfileDB

 #Libs
diff --git a/EbonyUtilities.lua b/EbonyUtilities.lua
index 95c65a0..d643f23 100644
--- a/EbonyUtilities.lua
+++ b/EbonyUtilities.lua
@@ -262,6 +262,7 @@ function EbonyUtilities:TooltipScaner(item)
 				text = tooltipText
 				text2 = tooltipTextTwo
 			--print("test9", text, text2)
+			tooltipScanner:Hide()
 			tooltipScanner:ClearLines()
 		end
 	return text, text2
diff --git a/Modules/ItemUse-Classic.lua b/Modules/ItemUse-Classic.lua
index 2544f78..922775e 100644
--- a/Modules/ItemUse-Classic.lua
+++ b/Modules/ItemUse-Classic.lua
@@ -484,9 +484,10 @@ function EMA:CheckForQuestItemAndAddToBar()
 		for slot = 1, GetContainerNumSlots(bag) do
 			local itemLink = GetContainerItemLink(bag, slot)
 			if itemLink and itemLink:match("item:%d") then
-				local tooltipText = EMAUtilities:TooltipScaner(itemLink)
-				if tooltipText and tooltipText:match(ITEM_BIND_QUEST) then
-					local spellName, spellID = GetItemSpell( itemLink )
+				local name, itemLink,_,_,_,itemType,questItem = GetItemInfo( itemLink )
+				--EMA:Print("test", itemType,questItem )
+				if itemType ~= nil and itemType == "Quest" then
+				local spellName, spellID = GetItemSpell( itemLink )
 					if spellName then
 						--EMA:Print("test", itemLink, tooltipText )
 						EMA:AddAnItemToTheBarIfNotExists( itemLink, false )