------------------------------------------------------
-- Expbar Module
------------------------------------------------------
local T, C, L, _ = unpack(select(2, ...))
local cfg = C.Module.Actionbar.bars.expbar

if cfg.enable ~= true then return end

if cfg.disable_at_max_lvl and T.level == MAX_PLAYER_LEVEL then return end

cfg.bflevel             = 2
cfg.bfstrata            = "LOW"
cfg.statusbar           = C.Media.Texture.status
cfg.xpcolor             = {r = 0.8, g = 0, b = 0.8}
cfg.repcolor            = {r = 1, g = 0.6, b = 0}
cfg.restcolor           = {r = 1, g = 0.7, b = 0}

------------------------------------------------------
-- / Auto Rep Switch FUNCs / --
------------------------------------------------------

local f = CreateFrame("Frame")

local strMatchCombat = {}
tinsert(strMatchCombat, (string.gsub(FACTION_STANDING_INCREASED,"%%%d?%$?s", "(.+)")))
tinsert(strMatchCombat, (string.gsub(FACTION_STANDING_INCREASED_GENERIC,"%%%d?%$?s", "(.+)")))
tinsert(strMatchCombat, (string.gsub(FACTION_STANDING_INCREASED_BONUS,"%%%d?%$?s", "(.+)")))
tinsert(strMatchCombat, (string.gsub(FACTION_STANDING_INCREASED_DOUBLE_BONUS,"%%%d?%$?s", "(.+)")))
tinsert(strMatchCombat, (string.gsub(FACTION_STANDING_INCREASED_ACH_BONUS,"%%%d?%$?s", "(.+)")))

local strGuildChangeMatch = {}
local strChangeMatch = (string.gsub(FACTION_STANDING_CHANGED,"%%%d?%$?s", "(.+)"))
tinsert(strGuildChangeMatch, (string.gsub(FACTION_STANDING_CHANGED_GUILD,"%%%d?%$?s", "(.+)")))
tinsert(strGuildChangeMatch, (string.gsub(FACTION_STANDING_CHANGED_GUILDNAME,"%%%d?%$?s", "(.+)")))

local collapsed = {}
local guildName

f:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE")
f:RegisterEvent("COMBAT_TEXT_UPDATE")
f:RegisterEvent("CHAT_MSG_SYSTEM")
f:RegisterEvent("PLAYER_LOGIN")
f:RegisterEvent("PLAYER_GUILD_UPDATE")

f:SetScript("OnEvent", 
function(self, event, ...) 
    if self[event] then
        return self[event](...)
    end
end)

local function setWatchedFaction(faction)
    wipe(collapsed)
    local i,j = 1, GetNumFactions()
    while i <= j do
        local name,_,_,_,_,_,_,_,isHeader,isCollapsed,_,isWatched = GetFactionInfo(i)
        if name == faction then
            if not (isWatched or IsFactionInactive(i)) then
                SetWatchedFactionIndex(i)
            end
            break
        end
        if isHeader and isCollapsed then
            ExpandFactionHeader(i)
            collapsed[i] = true
            j = GetNumFactions()
        end
        i = i+1
    end
    -- let's clean up after ourselves
    if next(collapsed) then
        for k=i,1,-1 do
            if collapsed[k] then
                CollapseFactionHeader(k)
            end
        end
    end
end

function f.GUILD_ROSTER_UPDATE()
    if IsInGuild() then
        guildName = (GetGuildInfo("player"))
    end
    if guildName then
        f:UnregisterEvent("GUILD_ROSTER_UPDATE")
    end
end
function f.PLAYER_GUILD_UPDATE()
    if IsInGuild() then
        guildName = (GetGuildInfo("player"))
        if not guildName then 
            f:RegisterEvent("GUILD_ROSTER_UPDATE")
        end
    else
        guildName = nil
    end
end

function f.PLAYER_LOGIN()
    if IsInGuild() then
        guildName = (GetGuildInfo("player"))
        if not guildName then 
            f:RegisterEvent("GUILD_ROSTER_UPDATE")
        end
    end
end

function f.CHAT_MSG_SYSTEM(...)
    local messg = ...
    local found
    local newfaction = (string.match(messg,strChangeMatch)) and select(2,string.match(messg,strChangeMatch))
    if newfaction then
        if guildName and (newfaction == GUILD) then
            found = guildName
        else
            found = newfaction
        end
    else
        local guildfaction
        for i, v in ipairs(strGuildChangeMatch) do
            guildfaction = (string.match(messg,strGuildChangeMatch[i]))
            if guildfaction then
                break
            end
        end
        if guildfaction and guildName then
            found = guildName
        end
    end
    if found then
        setWatchedFaction(found)
    end
end

function f.COMBAT_TEXT_UPDATE(...)
    local messagetype, faction, amount = ...
    if messagetype ~= "FACTION" then return end
    if (not amount) or (amount<0) then return end
    if GUILD and faction and guildName and (faction == GUILD) then
        faction = guildName
    end
    if faction then
        setWatchedFaction(faction)
    end
end

function f.CHAT_MSG_COMBAT_FACTION_CHANGE(...)
    local messg = ...
    local found
    for i, v in ipairs(strMatchCombat) do
        found = (string.match(messg,strMatchCombat[i]))
        if found then
            if GUILD and guildName and (found == GUILD) then
                found = guildName
            end

            break
        end
    end
    if found then
        setWatchedFaction(found)
    end
end

------------------------------------------------------
-- / Bar FUNCs / --
------------------------------------------------------

local statusbar

--update bar
local function updateBar(repbar)
  if not repbar then
    local min, max = UnitXP("player"), UnitXPMax("player")
    local exhaustion = GetXPExhaustion() or 0 

    statusbar:SetMinMaxValues(0, max)
    statusbar:SetValue(min)
    statusbar.rest:SetMinMaxValues(0, max)
    statusbar.rest:SetValue(math.min(min + exhaustion, max)) 
  else
    local name, standing, min, max, value = GetWatchedFactionInfo()

    if not name then return end

    local color = FACTION_BAR_COLORS[standing]
    statusbar:SetStatusBarColor(color.r, color.g, color.b)
    statusbar:SetMinMaxValues(0, max - min)
    statusbar:SetValue(value - min)
  end
end

--showxp
local function bar_showXP()
  statusbar:SetStatusBarColor(cfg.xpcolor.r, cfg.xpcolor.g, cfg.xpcolor.b, 0.85)
  statusbar.background:SetVertexColor(cfg.xpcolor.r, cfg.xpcolor.g, cfg.xpcolor.b, 0.3)

  statusbar.rest:Show()

  updateBar()
end
  
--showrep
local function bar_showRep()
  statusbar.rest:Hide()

  updateBar(true)
end
    
--onevent
local function bar_OnEvent(this, event, arg1, arg2, arg3, arg4, ...)
  if event == "PLAYER_ENTERING_WORLD" then
    if T.level == MAX_PLAYER_LEVEL then
      bar_showRep()
    else
      bar_showXP()
    end
  elseif event == "PLAYER_XP_UPDATE" and arg1 == "player" then
    updateBar()
  elseif event == "PLAYER_LEVEL_UP" then
    if T.level == MAX_PLAYER_LEVEL then
      bar_showRep()
    else
      bar_showXP()
    end
  elseif event == "MODIFIER_STATE_CHANGED" then
    if arg1 == "LCTRL" or arg1 == "RCTRL" then
      if arg2 == 1 then
        bar_showRep()
      elseif arg2 == 0 and T.level ~= MAX_PLAYER_LEVEL then
        bar_showXP()
      end
    end
  elseif event == "UPDATE_FACTION" then
    if T.level == MAX_PLAYER_LEVEL then
      bar_showRep()
    end
  end
end
  
--onenter
local function bar_OnEnter()
    mxp = UnitXPMax("player")
    xp = UnitXP("player")
    rxp = GetXPExhaustion()
    name, standing, minrep, maxrep, value = GetWatchedFactionInfo()

    GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR")

    if T.level ~= MAX_PLAYER_LEVEL then
        GameTooltip:AddLine(L.ACTIONBAR_EXP)
        GameTooltip:AddDoubleLine(COMBAT_XP_GAIN, xp.."|cffffd100/|r"..mxp.." |cffffd100/|r "..floor((xp/mxp)*1000)/10 .."%",NORMAL_FONT_COLOR.r,NORMAL_FONT_COLOR.g,NORMAL_FONT_COLOR.b,1,1,1)
        if rxp then
            GameTooltip:AddDoubleLine(TUTORIAL_TITLE26, rxp .." |cffffd100/|r ".. floor((rxp/mxp)*1000)/10 .."%", NORMAL_FONT_COLOR.r,NORMAL_FONT_COLOR.g,NORMAL_FONT_COLOR.b,1,1,1)
        end
        if name then
            GameTooltip:AddLine(" ")
        end
    end

    if name then
        GameTooltip:AddLine(L.ACTIONBAR_REP)
        GameTooltip:AddDoubleLine(FACTION, name, NORMAL_FONT_COLOR.r,NORMAL_FONT_COLOR.g,NORMAL_FONT_COLOR.b,1,1,1)
        GameTooltip:AddDoubleLine(STANDING, getglobal("FACTION_STANDING_LABEL"..standing), NORMAL_FONT_COLOR.r,NORMAL_FONT_COLOR.g,NORMAL_FONT_COLOR.b,FACTION_BAR_COLORS[standing].r, FACTION_BAR_COLORS[standing].g, FACTION_BAR_COLORS[standing].b)
        GameTooltip:AddDoubleLine(REPUTATION, value-minrep .."|cffffd100 /|r"..maxrep-minrep.." |cffffd100/|r "..floor((value-minrep)/(maxrep-minrep)*1000)/10 .."%", NORMAL_FONT_COLOR.r,NORMAL_FONT_COLOR.g,NORMAL_FONT_COLOR.b,1,1,1)
    end

    GameTooltip:Show()
end

--onleave
local function bar_OnLeave()
    GameTooltip:Hide()
end
  
------------------------------------------------------
-- / CREATE THE BAR / --
------------------------------------------------------
local createbar = function()
    statusbar = CreateFrame("StatusBar", nil, UIParent)
    statusbar:SetFrameStrata(cfg.bfstrata)
    statusbar:SetFrameLevel(cfg.bflevel)
    statusbar:SetSize(cfg.width, cfg.height)
    statusbar:SetPoint(unpack(cfg.pos))
    statusbar:SetScale(cfg.scale)
    statusbar:SetStatusBarTexture(cfg.statusbar)
    statusbar:SetStatusBarColor(cfg.xpcolor.r, cfg.xpcolor.g, cfg.xpcolor.b)

    statusbar.rest = CreateFrame("Statusbar", nil, statusbar)
    statusbar.rest:SetAllPoints(statusbar)
    statusbar.rest:SetStatusBarTexture(cfg.texture)
    statusbar.rest:SetStatusBarColor(cfg.restcolor.r,cfg.restcolor.g,cfg.restcolor.b)

    statusbar.background = statusbar:CreateTexture(nil, "BACKGROUND", nil, -8)
    statusbar.background:SetAllPoints(statusbar)
    statusbar.background:SetTexture(cfg.statusbar)
    statusbar.background:SetVertexColor(cfg.xpcolor.r, cfg.xpcolor.g, cfg.xpcolor.b, 0.3)

    statusbar:SetScript("OnEvent", bar_OnEvent)
    statusbar:SetScript("OnEnter", bar_OnEnter)
    statusbar:SetScript("OnLeave", bar_OnLeave)

    statusbar:RegisterEvent("PLAYER_XP_UPDATE")
    statusbar:RegisterEvent("PLAYER_LEVEL_UP")
    statusbar:RegisterEvent("PLAYER_ENTERING_WORLD")
    statusbar:RegisterEvent("UPDATE_FACTION")
    statusbar:RegisterEvent("MODIFIER_STATE_CHANGED")
end

------------------------------------------------------
-- / LOAD IT / --
------------------------------------------------------  

local a = CreateFrame("Frame")
a:RegisterEvent("VARIABLES_LOADED")
a:SetScript("OnEvent", function(self)
  self:UnregisterEvent("VARIABLES_LOADED")
  self:SetScript("OnEvent", nil)
  createbar()
end)