local Azurah = _G['Azurah'] -- grab addon table from global
local LMP = LibStub('LibMediaProvider-1.0')

-- UPVALUES --
local IsUnitVeteran                 = IsUnitVeteran
local GetUnitVeteranPoints          = GetUnitVeteranPoints
local GetUnitVeteranPointsMax       = GetUnitVeteranPointsMax
local GetUnitXP                     = GetUnitXP
local GetUnitXPMax                  = GetUnitXPMax
local GetMaxVeteranRank             = GetMaxVeteranRank
local IsChampionSystemUnlocked      = IsChampionSystemUnlocked
local GetPlayerChampionXP           = GetPlayerChampionXP
local GetChampionXPInRank           = GetChampionXPInRank
local GetPlayerChampionPointsEarned = GetPlayerChampionPointsEarned
local strformat                     = string.format
local zo_callLater                  = zo_callLater
local overlayExp
local overlayChamp
local FormatExp
local db
local isUpdating
local hasMaxXP = false
local hasMaxCP = false

local function OnCraftStart()
    if (db.displayStyle == 2) then
        ZO_PlayerProgressBar:SetAlpha(0)
    end
end

local function OnCraftEnd()
    if (db.displayStyle == 2) then
        ZO_PlayerProgressBar:SetAlpha(1)
    end
end

local function UpdateExperienceBarOverlayValues()
    local isVeteran = IsUnitVeteran('player')

    if (not hasMaxXP) then
        local current, max

        if (isVeteran) then
            current, max = GetUnitVeteranPoints('player'), GetUnitVeteranPointsMax('player')
            hasMaxXP = (GetUnitVeteranRank('player') == GetMaxVeteranRank()) and (current >= max)
        else
            current, max = GetUnitXP('player'), GetUnitXPMax('player')
        end

        overlayExp:SetText(FormatExp(current, nil, max))
    end

    if (not hasMaxCP and isVeteran) then
        if (IsChampionSystemUnlocked()) then
            local earnedCP = GetPlayerChampionPointsEarned()
            local inRankCP = GetChampionXPInRank(earnedCP)
            if (inRankCP ~= nil) then
                local championXP = GetPlayerChampionXP()
                overlayChamp:SetText(strformat("%d - %s", earnedCP, FormatExp(championXP, nil, inRankCP)))
            end
            hasMaxCP = earnedCP == 3600
        end
    end

    isUpdating = false
end

local function OnExpGain(_, unit)
    if (unit ~= 'player') then return end -- only care about the player

    if (not isUpdating) then
        isUpdating = true
        zo_callLater(UpdateExperienceBarOverlayValues, 1000)
    end
end

function Azurah:ConfigureExperienceBarOverlay()
    if (not IsInGamepadPreferredMode() and db.overlay > 1) then -- showing overlay, enable tracking
        local current, max, earnedCP, inRankCP
        local isVeteran = IsUnitVeteran('player')

        local fontStr = strformat('%s|%d|%s', LMP:Fetch('font', db.fontFace), db.fontSize, db.fontOutline)
        FormatExp = self.overlayFuncs[db.overlay + ((db.overlayFancy) and 10 or 0)]

        overlayExp:SetFont(fontStr)
        overlayExp:SetColor(db.fontColour.r, db.fontColour.g, db.fontColour.b, db.fontColour.a)
        overlayChamp:SetFont(fontStr)
        overlayChamp:SetColor(db.fontColour.r, db.fontColour.g, db.fontColour.b, db.fontColour.a)

        if (isVeteran) then
            current  = GetUnitVeteranPoints('player')
            max      = GetUnitVeteranPointsMax('player')
            earnedCP = GetPlayerChampionPointsEarned()
            inRankCP = GetChampionXPInRank(earnedCP)
            hasMaxXP = (GetUnitVeteranRank('player') == GetMaxVeteranRank()) and (current >= max)
            hasMaxCP = earnedCP == 3600
        else
            current, max = GetUnitXP('player'), GetUnitXPMax('player')
        end

        if (not hasMaxXP) then
            --hide "LEVEL"/"VETERAN RANK" text
            ZO_PlayerProgressLevelType:SetAlpha(0)
            overlayExp:SetHidden(false)
            overlayExp:SetText(FormatExp(current, nil, max))
        else
            ZO_PlayerProgressLevelType:SetAlpha(1)
            overlayExp:SetHidden(true)
        end

        if (IsChampionSystemUnlocked() and isVeteran and not hasMaxCP) then
            --hide "CHAMPION POINT" text
            ZO_PlayerProgressSecondaryLevelType:SetAlpha(0)
            overlayChamp:SetHidden(false)
            overlayChamp:SetText(strformat("%d - %s", earnedCP, FormatExp(GetPlayerChampionXP(), nil, inRankCP)))
        else
            ZO_PlayerProgressSecondaryLevelType:SetAlpha(1)
            overlayChamp:SetHidden(true)
        end

        EVENT_MANAGER:RegisterForEvent(self.name .. 'Experience', EVENT_EXPERIENCE_UPDATE, OnExpGain)
        EVENT_MANAGER:RegisterForEvent(self.name .. 'Experience', EVENT_VETERAN_POINTS_UPDATE, OnExpGain)

    else -- no overlay being shown, disable tracking
        EVENT_MANAGER:UnregisterForEvent(self.name .. 'Experience', EVENT_EXPERIENCE_UPDATE)
        EVENT_MANAGER:UnregisterForEvent(self.name .. 'Experience', EVENT_VETERAN_POINTS_UPDATE)

        overlayExp:SetHidden(true)
        overlayChamp:SetHidden(true)

        --restore visibility of "LEVEL"/"VETERAN RANK" and "CHAMPION POINT" texts
        ZO_PlayerProgressLevelType:SetAlpha(1)
        ZO_PlayerProgressSecondaryLevelType:SetAlpha(1)
    end
end

function Azurah:ConfigureExperienceBarDisplay()
    -- Visibility code for Experience Bar is by Garkin (http://www.esoui.com/forums/member.php?u=524)\and used with permission.
    PLAYER_PROGRESS_BAR_FRAGMENT:SetConditional(function() return not (db.displayStyle == 3) end)
    PLAYER_PROGRESS_BAR_CURRENT_FRAGMENT:SetConditional(function() return not (db.displayStyle == 3) end)

    if (db.displayStyle == 2) then
        EVENT_MANAGER:RegisterForEvent(self.name .. 'Experience', EVENT_CRAFTING_STATION_INTERACT,      OnCraftStart)
        EVENT_MANAGER:RegisterForEvent(self.name .. 'Experience', EVENT_END_CRAFTING_STATION_INTERACT,  OnCraftEnd)
        HUD_SCENE:AddFragment(PLAYER_PROGRESS_BAR_FRAGMENT)
        HUD_SCENE:AddFragment(PLAYER_PROGRESS_BAR_CURRENT_FRAGMENT)
        HUD_UI_SCENE:AddFragment(PLAYER_PROGRESS_BAR_FRAGMENT)
        HUD_UI_SCENE:AddFragment(PLAYER_PROGRESS_BAR_CURRENT_FRAGMENT)
    else
        EVENT_MANAGER:UnregisterForEvent(self.name .. 'Experience', EVENT_CRAFTING_STATION_INTERACT)
        EVENT_MANAGER:UnregisterForEvent(self.name .. 'Experience', EVENT_END_CRAFTING_STATION_INTERACT)
        HUD_SCENE:RemoveFragment(PLAYER_PROGRESS_BAR_FRAGMENT)
        HUD_SCENE:RemoveFragment(PLAYER_PROGRESS_BAR_CURRENT_FRAGMENT)
        HUD_UI_SCENE:RemoveFragment(PLAYER_PROGRESS_BAR_FRAGMENT)
        HUD_UI_SCENE:RemoveFragment(PLAYER_PROGRESS_BAR_CURRENT_FRAGMENT)
    end
end

function Azurah:InitializeExperienceBar()
    db = self.db.experienceBar

    --I'm not sure where I have to show overlay, so I'll replace "VETERAN RANK" and "CHAMPION POINT" texts
    overlayExp = self:CreateOverlay(ZO_PlayerProgressBar, BOTTOMLEFT, TOPLEFT, 4, -2, nil, nil, nil, TEXT_ALIGN_LEFT)
    overlayChamp = self:CreateOverlay(ZO_PlayerProgressSecondaryLevelTypeIcon, LEFT, RIGHT, 8, 0, nil, nil, nil, TEXT_ALIGN_LEFT)

    if IsUnitVeteran('player') then
        overlayExp:ClearAnchors()
        overlayExp:SetAnchor(LEFT, ZO_PlayerProgressLevelTypeIcon, RIGHT, 8, 0)
    end

    -- set 'dummy' display function
    FormatExp = self.overlayFuncs[1]

    self:ConfigureExperienceBarOverlay()
    self:ConfigureExperienceBarDisplay()
end