--[[
	Addon: Taos Group Tools
	Author: TProg Taonnor
	Created by @Taonnor
]]--

--[[
	Local variables
]]--
local LOG_ACTIVE = false

local REFRESHRATE = 1000 -- ms; RegisterForUpdate is in miliseconds
local TIMEOUT = 4 -- s; GetTimeStamp() is in seconds

local _logger = nil
local _control = nil
local _isActive = false
local _players = {}

--[[
	Table TGT_SimpleList
]]--
TGT_SimpleList = {}
TGT_SimpleList.__index = TGT_SimpleList

--[[
	Table Members
]]--

--[[
	Sets visibility of labels
]]--
function TGT_SimpleList.RefreshList()
	if (LOG_ACTIVE) then _logger:logTrace("TGT_SimpleList.RefreshList") end

    for i=1, GROUP_SIZE_MAX, 1 do
        local row = TGT_SimpleListControlContainerScrollChild:GetNamedChild("Row" .. i)
        local listPlayer = _players[i]

        if (listPlayer ~= nil) then
            local isPlayerNotGrouped = IsUnitGrouped(listPlayer.PingTag) == false
            local isPlayerTimedOut = (GetTimeStamp() - listPlayer.LastMapPingTimestamp) > TIMEOUT

            if (isPlayerNotGrouped or isPlayerTimedOut) then
                if (LOG_ACTIVE) then _logger:logDebug("Player invalid, hide row: " .. tostring(i)) end

                row:SetHidden(true)
                table.remove(_players, i)
            end
        else
            if (LOG_ACTIVE) then _logger:logDebug("Row empty, hide: " .. tostring(i)) end
            row:SetHidden(true)
        end
    end

	if (TGT_SettingsHandler.SavedVariables.IsSortingActive) then
		-- Sort list with all players
		TGT_SimpleList.SortList()
	end
end

--[[
	Sorts swimlane
]]--
function TGT_SimpleList.SortList()
	if (LOG_ACTIVE) then _logger:logTrace("TGT_SimpleList.SortList") end

    -- Comparer
    function compare(playerLeft, playerRight)
        if (playerLeft.RelativeUltimate == playerRight.RelativeUltimate) then
            return playerLeft.PingTag < playerRight.PingTag
        else
            return playerLeft.RelativeUltimate > playerRight.RelativeUltimate
        end
    end

    table.sort(_players, compare)

    -- Update sorted swimlane list
    for i,listPlayer in ipairs(_players) do
        TGT_SimpleList.UpdateListRow(TGT_SimpleListControlContainerScrollChild:GetNamedChild("Row" .. i), listPlayer)
    end
end

--[[
	Updates list row
]]--
function TGT_SimpleList.UpdateListRow(row, player)
	if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.UpdateListRow")
    end

    local localizedUltimateName = zo_strformat(SI_ABILITY_TOOLTIP_NAME, player.UltimateName)
    local nameLength = string.len(localizedUltimateName)

    if (nameLength > 22) then
        localizedUltimateName = string.sub(localizedUltimateName, 0, 22) .. "..."
    end

    row:GetNamedChild("SenderNameValueLabel"):SetText(player.PlayerName)
	row:GetNamedChild("UltimateValueLabel"):SetText(localizedUltimateName)
	row:GetNamedChild("ReadyValueLabel"):SetText(player.RelativeUltimate)

	if (player.IsPlayerDead) then
        row:GetNamedChild("SenderNameValueLabel"):SetColor(1.0, 0.0, 0.0, 1)
		row:GetNamedChild("UltimateValueLabel"):SetColor(1.0, 0.0, 0.0, 1)
		row:GetNamedChild("ReadyValueLabel"):SetColor(1.0, 0.0, 0.0, 1)
    elseif (player.RelativeUltimate == 100) then
		row:GetNamedChild("SenderNameValueLabel"):SetColor(0.0, 1.0, 0.0, 1)
		row:GetNamedChild("UltimateValueLabel"):SetColor(0.0, 1.0, 0.0, 1)
		row:GetNamedChild("ReadyValueLabel"):SetColor(0.0, 1.0, 0.0, 1)
	else
		row:GetNamedChild("SenderNameValueLabel"):SetColor(1.0, 1.0, 1.0, 1)
		row:GetNamedChild("UltimateValueLabel"):SetColor(1.0, 1.0, 1.0, 1)
		row:GetNamedChild("ReadyValueLabel"):SetColor(1.0, 1.0, 1.0, 1)
	end

    if (row:IsHidden()) then
		row:SetHidden(false)
	end
end

--[[
	Updates list row
]]--
function TGT_SimpleList.UpdatePlayer(player)
	if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.UpdatePlayer")
    end

	if (player) then
        local row = nil

        for i,listPlayer in ipairs(_players) do
            if (LOG_ACTIVE) then _logger:logDebug(listPlayer.PlayerName .. " == " .. player.PlayerName) end
		    if (listPlayer.PlayerName == player.PlayerName) then
                row = TGT_SimpleListControlContainerScrollChild:GetNamedChild("Row" .. i)
            end
	    end

        local updateNeeded = true

        -- Update timestamp
		if (row ~= nil) then
            for i,listPlayer in ipairs(_players) do
		        if (listPlayer.PlayerName == player.PlayerName) then
                    listPlayer.LastMapPingTimestamp = GetTimeStamp()

                    updateNeeded = listPlayer.IsPlayerDead ~= player.IsPlayerDead or listPlayer.RelativeUltimate ~= player.RelativeUltimate

                    if (listPlayer.RelativeUltimate > player.RelativeUltimate) then
                        local sound = TGT_SettingsHandler.SavedVariables.Sound
                        if (sound[1] > 1) then PlaySound(SOUNDS[sound[2]]) end
					end

                    listPlayer.IsPlayerDead = player.IsPlayerDead
                    listPlayer.RelativeUltimate = player.RelativeUltimate
                    break
                end
	        end
        else
            -- Add new player
            local nextFreeRow = 1

            for i,player in ipairs(_players) do
		        nextFreeRow = nextFreeRow + 1
	        end

            if (nextFreeRow <= GROUP_SIZE_MAX) then
                if (LOG_ACTIVE) then
                    _logger:logDebug("TGT_SimpleList.UpdatePlayer, add player " .. tostring(player.PlayerName) .. " to row " .. tostring(nextFreeRow))
                end

                player.LastMapPingTimestamp = GetTimeStamp()
                _players[nextFreeRow] = player
                row = TGT_SimpleListControlContainerScrollChild:GetNamedChild("Row" .. nextFreeRow)
            else
                if (LOG_ACTIVE) then _logger:logDebug("TGT_SimpleList.UpdatePlayer, too much players for list" .. tostring(nextFreeRow)) end
            end
        end

        -- Only update if player in a row
        if (row ~= nil and updateNeeded) then
            -- Directly update row with player, sorting will be triggered on RefreshList
			TGT_SimpleList.UpdateListRow(row, player)
        end
    end
end

--[[
	SetControlMovable sets the Movable and MouseEnabled flag in UI elements
]]--
function TGT_SimpleList.SetControlMovable(isMovable)
    if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.SetControlMovable")
        _logger:logDebug("isMovable", isMovable)
    end

    _control:GetNamedChild("MovableControl"):SetHidden(isMovable == false)

    _control:SetMovable(isMovable)
	_control:SetMouseEnabled(isMovable)
end

--[[
	RestorePosition sets TGT_SimpleList on settings position
]]--
function TGT_SimpleList.RestorePosition(posX, posY)
    if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.RestorePosition")
        _logger:logDebug("posX, posY", posX, posY)
    end

	_control:ClearAnchors()
	_control:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, posX, posY)
end

--[[
	OnSimpleListMoveStop saves current TGT_SimpleList position to settings
]]--
function TGT_SimpleList.OnSimpleListMoveStop()
    if (LOG_ACTIVE) then _logger:logTrace("TGT_SimpleList.OnSimpleListMoveStop") end

	local left = _control:GetLeft()
	local top = _control:GetTop()

    TGT_SettingsHandler.SavedVariables.PosX = left
    TGT_SettingsHandler.SavedVariables.PosY = top

    if (LOG_ACTIVE) then
        _logger:logDebug("PosX, PosY", TGT_SettingsHandler.SavedVariables.PosX, TGT_SettingsHandler.SavedVariables.PosY)
    end
end

--[[
	SetControlHidden sets hidden on control
]]--
function TGT_SimpleList.SetControlHidden()
    if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.SetControlHidden")
    end

    -- Get isActive from settings
    local isActive = TGT_SettingsHandler.IsSimpleListVisible()
    if (LOG_ACTIVE) then _logger:logDebug("isActive", isActive) end

    if (isActive) then
        if (GetIsUnitGrouped() and GetGroupSize() >= TGT_SettingsHandler.SavedVariables.VisibleOffset) then
            _control:SetHidden(CurrentHudHiddenState())
        else
            _control:SetHidden(true)
        end
    else
        _control:SetHidden(true)
    end
end

--[[
	SetControlActive sets hidden on control
]]--
function TGT_SimpleList.SetControlActive()
    if (LOG_ACTIVE) then
        _logger:logTrace("TGT_SimpleList.SetControlActive")
    end

    TGT_SimpleList.SetControlHidden()

    -- Get isActive from settings
    local isActive = TGT_SettingsHandler.IsSimpleListVisible()
    if (LOG_ACTIVE) then _logger:logDebug("isActive", isActive) end

    if (_isActive ~= isActive) then
        _isActive = isActive

        if (isActive) then
            if (LOG_ACTIVE) then _logger:logDebug("TGT_SimpleList.SetControlActive RegisterCallbacks") end

            TGT_SimpleList.SetControlMovable(TGT_SettingsHandler.SavedVariables.Movable)
            TGT_SimpleList.RestorePosition(TGT_SettingsHandler.SavedVariables.PosX, TGT_SettingsHandler.SavedVariables.PosY)

		    -- Start timeout timer
	        EVENT_MANAGER:RegisterForUpdate(TGT_SimpleList.Name, REFRESHRATE, TGT_SimpleList.RefreshList)

            CALLBACK_MANAGER:RegisterCallback(TAO_GROUP_CHANGED, TGT_SimpleList.RefreshList)
            CALLBACK_MANAGER:RegisterCallback(TGT_PLAYER_DATA_CHANGED, TGT_SimpleList.UpdatePlayer)
            CALLBACK_MANAGER:RegisterCallback(TGT_MOVABLE_CHANGED, TGT_SimpleList.SetControlMovable)
            CALLBACK_MANAGER:RegisterCallback(TAO_HUD_HIDDEN_STATE_CHANGED, TGT_SimpleList.SetControlHidden)
            CALLBACK_MANAGER:RegisterCallback(TGT_VISIBLE_OFFSET_CHANGED, TGT_SimpleList.SetControlHidden)
        else
            if (LOG_ACTIVE) then _logger:logDebug("TGT_SimpleList.SetControlActive UnregisterCallbacks") end

            -- Stop timeout timer
	        EVENT_MANAGER:UnregisterForUpdate(TGT_SimpleList.Name)

            CALLBACK_MANAGER:UnregisterCallback(TAO_GROUP_CHANGED, TGT_SimpleList.RefreshList)
            CALLBACK_MANAGER:UnregisterCallback(TGT_PLAYER_DATA_CHANGED, TGT_SimpleList.UpdatePlayer)
            CALLBACK_MANAGER:UnregisterCallback(TGT_MOVABLE_CHANGED, TGT_SimpleList.SetControlMovable)
            CALLBACK_MANAGER:UnregisterCallback(TAO_HUD_HIDDEN_STATE_CHANGED, TGT_SimpleList.SetControlHidden)
            CALLBACK_MANAGER:UnregisterCallback(TGT_VISIBLE_OFFSET_CHANGED, TGT_SimpleList.SetControlHidden)
        end
    else
        if (LOG_ACTIVE) then _logger:logDebug("_isActive == isActive; State not changed, do not update") end
    end
end

--[[
	CreateSimpleListRows creates simple list rows
]]--
function TGT_SimpleList.CreateSimpleListRows()
    if (LOG_ACTIVE) then _logger:logTrace("TGT_SimpleList.CreateSimpleListRows") end

	for i=1, GROUP_SIZE_MAX, 1 do
		local row = CreateControlFromVirtual("$(parent)Row", TGT_SimpleListControlContainerScrollChild, "GroupUltimateSimpleListRow", i)
        if (LOG_ACTIVE) then _logger:logDebug("Row created " .. row:GetName()) end

		row:SetHidden(true) -- initial not visible

		if i == 1 then
            row:SetAnchor(TOPLEFT, TGT_SimpleListControlContainerScrollChild, TOPLEFT, 0, 0)
        else
            row:SetAnchor(TOP, lastRow, BOTTOM, 0, 0)
        end

		lastRow = row
	end
end

--[[
	Initialize initializes TGT_SimpleList
]]--
function TGT_SimpleList.Initialize(logger)
    if (LOG_ACTIVE) then
        logger:logTrace("TGT_SimpleList.Initialize")
    end

    _logger = logger
    _control = TGT_SimpleListControl

    TGT_SimpleList.CreateSimpleListRows()
    TGT_SimpleList.SetControlActive()

    CALLBACK_MANAGER:RegisterCallback(TGT_STYLE_CHANGED, TGT_SimpleList.SetControlActive)
    CALLBACK_MANAGER:RegisterCallback(TGT_IS_ZONE_CHANGED, TGT_SimpleList.SetControlActive)
    CALLBACK_MANAGER:RegisterCallback(TAO_UNIT_GROUPED_CHANGED, TGT_SimpleList.SetControlActive)
end