--------------------------------------------------------------------------------
-- ChatBarAO Reloaded :)
--------------------------------------------------------------------------------
-- GLOBALS
--------------------------------------------------------------------------------

Global( "wtMainPanel", nil )
Global( "wtChatInput", nil )
Global( "btnChannel", {} )
Global( "vLastChannel", "say" )

--------------------------------------------------------------------------------
-- CHANNEL TYPE LOCALIZATIONS
--------------------------------------------------------------------------------

Global( "loc", "eng" )

Global( "description", {
	["rus"] = "Кнопки переключения каналов над чатом.",
	["eng"] = "Buttons to switch channels above the chat.",
	["ger"] = "Buttons schalten die Chat-Kanдle.",
	["fra"] = "Des boutons pour allumer le chat canaux.",
	["br"]  = "Botхes para mudar a canais de chat.",
	["jpn"] = "ѓ{ѓ^ѓ“‚Нѓ`ѓѓѓbѓgѓ`ѓѓѓ“ѓlѓ‹ђШ‚и‘Ц‚¦‚й‚±‚Ж‚Є‚Е‚«‚Ь‚·ЃB",
} )

Global( "channel", {
	["rus"] = {
		["say"]			= { letter = "S", name = "say" },
		["zone"]		= { letter = "Z", name = "zone" },
		["tell"]		= { letter = "-", name = "tell" },
		["reset"]		= { letter = "*", name = "reset" },
		["party"]		= { letter = "P", name = "party" },
		["raid"]		= { letter = "R", name = "raid" },
		["guild"]		= { letter = "G", name = "guild" },
		["officer"]		= { letter = "O", name = "officer" },
		["mystic"]		= { letter = "M", name = "mystic" },
		["yell"]		= { letter = "Y", name = "yell" },
		["world"]		= { letter = "W", name = "world" },
	},
	["eng"] = {
		["say"]			= { letter = "S", name = "say" },
		["zone"]		= { letter = "Z", name = "zone" },
		["tell"]		= { letter = "-", name = "whisper" },
		["reset"]		= { letter = "*", name = "reset" },
		["party"]		= { letter = "P", name = "party" },
		["raid"]		= { letter = "R", name = "raid" },
		["guild"]		= { letter = "G", name = "guild" },
		["officer"]		= { letter = "O", name = "officer" },
		["mystic"]		= { letter = "T", name = "telepathy" },
		["yell"]		= { letter = "Y", name = "shout" },
		["world"]		= { letter = "W", name = "world" },
	},
	["ger"] = {
		["say"]			= { letter = "S", name = "say" },
		["zone"]		= { letter = "Z", name = "zone" },
		["tell"]		= { letter = "-", name = "whisper" },
		["reset"]		= { letter = "*", name = "reset" },
		["party"]		= { letter = "P", name = "party" },
		["raid"]		= { letter = "R", name = "raid" },
		["guild"]		= { letter = "G", name = "guild" },
		["officer"]		= { letter = "O", name = "officer" },
		["mystic"]		= { letter = "T", name = "telepathy" },
		["yell"]		= { letter = "Y", name = "shout" },
		["world"]		= { letter = "W", name = "world" },
	},
	["fra"] = {
		["say"]			= { letter = "S", name = "say" },
		["zone"]		= { letter = "Z", name = "zone" },
		["tell"]		= { letter = "-", name = "whisper" },
		["reset"]		= { letter = "*", name = "reset" },
		["party"]		= { letter = "P", name = "party" },
		["raid"]		= { letter = "R", name = "raid" },
		["guild"]		= { letter = "G", name = "guild" },
		["officer"]		= { letter = "O", name = "officer" },
		["mystic"]		= { letter = "T", name = "telepathy" },
		["yell"]		= { letter = "Y", name = "shout" },
		["world"]		= { letter = "W", name = "world" },
	},
} )

-- Buttons positions
Global( "ButtonsPositions", {
		["say"]			= { pos = 0, vis = true},
		["zone"]		= { pos = 2, vis = true},
		["reset"]		= { pos = 3, vis = true},
		
		["party"]		= { pos = 4, vis = false},
		["raid"]		= { pos = 5, vis = false},
		["guild"]		= { pos = 6, vis = false},
		["officer"]		= { pos = 7, vis = false},
		
		["mystic"]		= { pos = 9, vis = false},
		["yell"]		= { pos = 10, vis = true},
		["world"]		= { pos = 11, vis = true}
} )

--------------------------------------------------------------------------------
-- HELPER FUNCTIONS
--------------------------------------------------------------------------------

-- AO game Version detection by SLA, ver. 2011-02-14.
function GetGameVersion()
	if avatar.GetUnlocks then return 2003
	elseif astral.GetAllTLs then return 2002
	elseif mount.SetSkin then return 2001
	elseif group.IsLeader then return 2000
	elseif social.GetFriendInfo then return 1104
	elseif not unit.IsDead then return 1103
	end
	return 1102
end

-- AO game Localization detection by SLA. Version 2011-02-10.
function GetGameLocalization()
	local B = cartographer.GetMapBlocks()
	local T = { rus="\203\232\227\224", eng="Holy Land", ger="Heiliges Land",
	fra="Terre Sacr\233e", br="Terra Sagrada", jpn="\131\74\131\106\131\65" }
	for b in B do for l,t in T do
	if userMods.FromWString( cartographer.GetMapBlockInfo(B[b]).name ) == t
	then return l end end end return "eng"
end

--------------------------------------------------------------------------------
-- ADDON FUNCTIONS
--------------------------------------------------------------------------------
function IsInParty()
	return group.GetMembers() ~= nil
end

function IsInRaid()
	return raid.IsExist()
end

function IsInGuild()
	local avRights
	if guild.GetMember then -- AO 1.1.03+
		avRights = guild.GetRights(guild.GetMember(object.GetName(avatar.GetId())))
	else -- AO 1.1.02
		avRights = guild.GetRights(object.GetName(avatar.GetId()))
	end
	for _,v in avRights do
		if v == GUILD_MEMBER_RIGHT_CHAT then
			return true
		end
	end
	return false
end

function IsOfficer()
	local avRights
	if guild.GetMember then -- AO 1.1.03+
		avRights = guild.GetRights(guild.GetMember(object.GetName(avatar.GetId())))
	else -- AO 1.1.02
		avRights = guild.GetRights(object.GetName(avatar.GetId()))
	end
	for _,v in avRights do
		if v == GUILD_MEMBER_RIGHT_OFFICER_CHAT then
			return true
		end
	end
	return false
end

-- Psionics have a special telepathy channel
function IsMyst()
	return ( avatar.GetClass() == "PSIONIC" )
end

function ManualChannelSwitch( params )
	mission.SetChatInputType( channel[ loc ][ params ].name )
end
--------------------------------------------------------------------------------
-- REACTION HANDLERS
--------------------------------------------------------------------------------

function OnChannelButtonPressed( params )
	mission.SetChatInputType( channel[ loc ][ params.sender ].name )
	if params.sender ~= "party" and params.sender ~= "raid" then
		vLastChannel = params.sender
	end

	wtChatInput:GetChildChecked( "Input", true ):SetFocus( true )
	wtChatInput:Show( true )
	common.RegisterEventHandler( OnEventSecondTimer, "EVENT_SECOND_TIMER" )
	common.RegisterEventHandler( OnEventChatMessage, "EVENT_CHAT_MESSAGE" )
end

--------------------------------------------------------------------------------
-- EVENT HANDLERS
--------------------------------------------------------------------------------

-- EVENT_GROUP_APPEARED
function OnEventGroupAppeared( params )
	btnChannel[ "party" ]:Show( true )
end

-- EVENT_GROUP_DISAPPEARED
function OnEventGroupDisappeared( params )
	btnChannel[ "party" ]:Show( false )
	ManualChannelSwitch( vLastChannel )
end

-- EVENT_RAID_APPEARED
function OnEventRaidAppeared( params )
	btnChannel[ "party" ]:Show( true )
	btnChannel[ "raid" ]:Show( true )
end

-- EVENT_RAID_DISAPPEARED
function OnEventRaidDisappeared( params )
	btnChannel[ "party" ]:Show( false )
	btnChannel[ "raid" ]:Show( false )
	ManualChannelSwitch( vLastChannel )
end

-- EVENT_GUILD_APPEARED 
function OnEventGuildAppeared( params )
	btnChannel[ "guild" ]:Show( true )
	btnChannel[ "officer" ]:Show( IsOfficer() )
end

-- EVENT_GUILD_DISAPPEARED
function OnEventGuildDisappeared( params )
	btnChannel[ "guild" ]:Show( false )
	btnChannel[ "officer" ]:Show( false )
	ManualChannelSwitch( "say" )
end

-- EVENT_GUILD_MEMBER_RANK_CHANGED
function OnEventGuildMemberRankChanged(params)
	btnChannel[ "officer" ]:Show( IsOfficer() )
end

-- EVENT_RAID_CHANGED -- EVENT_RAID_LEADER_CHANGED
function OnRaidChanged(params)
	btnChannel[ "raid" ]:Show( raid.IsExist() )
end

-- EVENT_CHAT_MESSAGE
function OnEventChatMessage( params )
	if params.senderId == avatar.GetId() then
		common.UnRegisterEventHandler( OnEventSecondTimer, "EVENT_SECOND_TIMER" )
		common.UnRegisterEventHandler( OnEventChatMessage, "EVENT_CHAT_MESSAGE" )
		wtChatInput:GetChildChecked( "Input", true ):SetFocus( false )
		wtChatInput:Show( false )
	end
end

-- EVENT_SECOND_TIMER
function OnEventSecondTimer()
	local input = mission.GetChatInput()
	if wtChatInput:GetChildChecked( "Input", true ):IsFocused() == false  and string.len(userMods.FromWString( input.text )) == 0 then
		local params = {}
		params.senderId = avatar.GetId()
		OnEventChatMessage(params)
	end
end

-- SCRIPT_ADDON_INFO_REQUEST
function OnAMAddonInfoRequest( params )
	if params.target == common.GetAddonName() then
		userMods.SendEvent( "SCRIPT_ADDON_INFO_RESPONSE", {
			sender = params.target,
			desc = description[ GetGameLocalization() ] or description[ "eng" ],
		} )
	end
end

-- SCRIPT_ADDON_MEM_REQUEST
function OnAMAddonMemoryRequest( params )
	if params.target == common.GetAddonName() then
		userMods.SendEvent( "SCRIPT_ADDON_MEM_RESPONSE", { sender = params.target, memUsage = gcinfo() } )
	end
end

-- ALT+Z Hiding
function OnToggleUI( params )
	wtMainPanel:Show( params.visible )
end

--------------------------------------------------------------------------------
-- INITIALIZATION
--------------------------------------------------------------------------------
function Init()
	-- Main Panel
	wtMainPanel = mainForm:GetChildChecked( "MainPanel", false )
	
	local Placement = wtMainPanel:GetChildChecked( "ChannelButton", false ):GetPlacementPlain()
	local wdChannelButtonDesc = wtMainPanel:GetChildChecked( "ChannelButton", false ):GetWidgetDesc()
	wtMainPanel:GetChildChecked( "ChannelButton", false ):DestroyWidget()
	wtChatInput = stateMainForm:GetChildChecked("ChatInput", true )
	if wtChatInput:GetChildChecked("ChatInput", false ) then
		wtChatInput = wtChatInput:GetChildChecked("ChatInput", true )
	end
	for i,param in ButtonsPositions do
		btnChannel[i] = mainForm:CreateWidgetByDesc( wdChannelButtonDesc )
		btnChannel[i]:SetName( i )
		btnChannel[i]:Show( param.vis )
		Placement.posX = param.pos * Placement.sizeX
		btnChannel[i]:SetPlacementPlain( Placement )
		wtMainPanel:AddChild( btnChannel[i] )
	end
	
	-- Registering Buttons' Reaction
	common.RegisterReactionHandler(OnChannelButtonPressed, "ButtonPressed")
	
	-- Post Initialization
	common.RegisterEventHandler( PostInit, "EVENT_AVATAR_CREATED" )
	-- Party events
	common.RegisterEventHandler( OnEventGroupAppeared, "EVENT_GROUP_APPEARED" )
	common.RegisterEventHandler( OnEventGroupDisappeared, "EVENT_GROUP_DISAPPEARED" )
	-- Raid events
	common.RegisterEventHandler( OnEventRaidAppeared, "EVENT_RAID_APPEARED" )
	common.RegisterEventHandler( OnEventRaidDisappeared, "EVENT_RAID_DISAPPEARED" )
	-- Guild events
	common.RegisterEventHandler( OnEventGuildAppeared, "EVENT_GUILD_APPEARED" )
	common.RegisterEventHandler( OnEventGuildDisappeared, "EVENT_GUILD_DISAPPEARED" )
	common.RegisterEventHandler( OnEventGuildMemberRankChanged, "EVENT_GUILD_MEMBER_RANK_CHANGED" )
	-- AddonManager support
	common.RegisterEventHandler( OnAMAddonInfoRequest, "SCRIPT_ADDON_INFO_REQUEST" )
	common.RegisterEventHandler( OnAMAddonMemoryRequest, "SCRIPT_ADDON_MEM_REQUEST" )
	common.RegisterEventHandler( OnToggleUI, "SCRIPT_TOGGLE_UI" )
	
	--common.RegisterEventHandler( OnStartChat, "EVENT_TEXT_OBJECT_CLICKED" )
	--common.RegisterEventHandler( OnStartChat, "SCRIPT_START_CHATTING" )
	--common.RegisterEventHandler( OnStartChat, "SCRIPT_CHAT_TALK_REPLY" )
	--common.RegisterEventHandler( OnStartChat, "SCRIPT_CHAT_SLASH_COMMAND" )
	--common.RegisterEventHandler( OnStartChat, "SCRIPT_REGISTER_TALK_REPLY" )
	--common.RegisterEventHandler( OnStartChat, "SCRIPT_POPUP_OPEN_CHAT_LINE" )
	
	-- Корректируем положение панели в предыдущих версиях АО (EU/US):
	-- Correcting main panel position in older AO versions (EU/US):
	if GetGameVersion() < 1104 then
		local p = wtMainPanel:GetPlacementPlain()
		-- Самое главное, до 1.1.04, приоритет mainForm должен быть гораздо ниже.
		-- Most important, before 1.1.04, mainForm priority must be much lower.
		if GetGameVersion() < 1104 then mainForm:SetPriority( 250 ) end
		-- До патча 1.1.03, слева 24 пикселя НЕ БЫЛИ закрыты чем-то невидимым.
		-- (Если поднять приоритет mainForm, то аддон закроет собой выпадающие меню с Настройками Чата).
		-- Prior to 1.1.03, first 24 pixels on the left WASN'T overlapped with some invisible in-game panel.
		-- (If I raise the mainForm priority, addon will overlap the Chat Configuration dropdown menu).
		if GetGameVersion() < 1103 then p.posX = 89 end
		-- И во всех версиях до 1.1.04, чат находился выше на 24 пикселя выше, по умолчанию.
		-- In all versions prior to 1.1.04, chat window was on 24 pixels higher position by default.
		if GetGameVersion() < 1104 then p.highPosY = 348 end
		wtMainPanel:SetPlacementPlain( p )
	end
	local p = wtMainPanel:GetPlacementPlain()
	p.highPosY = 375
	wtMainPanel:SetPlacementPlain( p )
	
	-- For the case addon was reloaded by AddonManager:
	if avatar.IsExist() then
		PostInit()
		btnChannel[ "guild" ]:Show( IsInGuild() )
		btnChannel[ "officer" ]:Show( IsOfficer() )
	end
end

-- Post Initialization
function PostInit()
	-- Getting game localization
	loc = GetGameLocalization()
	if not channel[ loc ] then
		loc = "eng"
	end
	
	-- Applying localization
	for i in ButtonsPositions do
		btnChannel[i]:SetVal( "value", userMods.ToWString( channel[ loc ][ i ].letter ) )
	end
	OnAMAddonInfoRequest( { target = common.GetAddonName() } )
	
	-- Enabling/disabling some buttons
	btnChannel[ "party" ]:Show( IsInParty() )
	btnChannel[ "raid" ]:Show( IsInRaid() )
	if IsInParty() == false then
		btnChannel[ "party" ]:Show( IsInRaid() )
	end
	btnChannel[ "mystic" ]:Show( IsMyst() )
end

--------------------------------------------------------------------------------
Init()
--------------------------------------------------------------------------------