-- This file is part of CyrHUD
--
-- (C) 2015 Scott Yeskie (Sasky)
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

CyrHUD = CyrHUD or {}

----------------------------------------------
-- Utility
----------------------------------------------
local function bl(val)
	if val == nil then return "NIL" elseif val then return "T" else return "F" end
end

local function nn(val)
    if val == nil then return "NIL" end
    return val
end

function CyrHUD.formatTime(delta, inclueSec)
    local sec = delta % 60
    delta = (delta - sec) / 60
    local min = delta % 60
    local out = min .. "m"

    if inclueSec then
        out = out .. " " .. sec .. "s"
    end
    return out
end

CyrHUD.errors = {}
function CyrHUD:error(val)
    if not self.errors[val] then
        self.errors[val] = 1
        d("|cFF0000ERROR (CyrHUD): " .. val .. "\n|CCCCCCCPlease file this bug info at |CEEEEFFesoui.com")
    end
end

----------------------------------------------
-- Events
----------------------------------------------
function CyrHUD.eventAttackChange(_, keepID, battlegroundContext, underAttack)
    local self = CyrHUD
    if underAttack then
        self:add(keepID)
    elseif self.battles[keepID] ~= nil then
        self.battles[keepID]:update()
    end
    self.battleContext = battlegroundContext
end

function CyrHUD.saveWindowPosition( window )
    local _, _, _, aP, x, y = window:GetAnchor()
    CyrHUD.cfg.anchPoint = aP
    CyrHUD.cfg.xoff = x
    CyrHUD.cfg.yoff = y
end

function CyrHUD.actionLayerChange(_, _, activeLayerIndex)
    CyrHUD_UI:SetHidden(activeLayerIndex > 2)
end

----------------------------------------------
-- Notification UI pool
----------------------------------------------
CyrHUD.entryCount = 0
CyrHUD.entries = {}

function CyrHUD:reconfigureLabels()
    for _,entry in pairs(self.entries) do
        --Forces reconfigure on next update
        entry.type = nil
    end
end

function CyrHUD:hideRow(index)
    if self.entries[index] then
        self.entries[index].main:SetHidden(true)
    end
end

function CyrHUD:getUIRow(index)
    if #self.entries < index then
        table.insert(self.entries, self.Label())
        index = #self.entries
    end
    self.entries[index].main:SetHidden(false)
    return self.entries[index]
end

function CyrHUD:printAll()
    local i = 1
    for _,status in ipairs(self.statusBars) do
        self:getUIRow(i):update(status)
        i = i + 1
    end

    for _,battle in pairs(self.battles) do
        self:getUIRow(i):update(battle)
        i = i + 1
    end
    for j=i,#self.entries do
        self:hideRow(j)
    end
end

----------------------------------------------
-- Battle management
----------------------------------------------
CyrHUD.battles = {}
function CyrHUD:add(keepID)
    if self.battles[keepID] == nil then
        self.battles[keepID] = self.Battle(keepID)
    else
        self.battles[keepID]:restart()
    end
end

function CyrHUD:checkAdd(keepID)
    if self.battles[keepID] == nil then
        local battle = self.Battle(keepID)
        if battle:isBattle() then
            self.battles[keepID] = battle
        end
    elseif self.battles[keepID]:isBattle() then
        self.battles[keepID]:restart()
    end
end

function CyrHUD:updateAll()
    for i,_ in pairs(self.battles) do
        --Update in-place
        self.battles[i]:update()
    end

    for _,status in pairs(self.statusBars) do
        status:update()
    end
end

function CyrHUD:scanKeeps()
    for i=3,20 do
        self:checkAdd(i)
    end

    for i=132,134 do
        self:checkAdd(i)
    end
end

------------------------------------------------------------------------
-- Initialization
------------------------------------------------------------------------
CyrHUD.visible = false
function CyrHUD:init()
    local _, pt, relTo, relPt = CyrHUD_UI:GetAnchor()
    self.ui:ClearAnchors()
    self.ui:SetAnchor(pt, relTo, CyrHUD.cfg.anchPoint or relPt, CyrHUD.cfg.xoff, CyrHUD.cfg.yoff)

    --Init UI
    self:disableQuestTrackers()
    self.ui:SetHidden(false)


    --Get initial scan
    self.battles = {}
    self.battleContext = BGQUERY_LOCAL
    self.campaign = GetCurrentCampaignId()
    self.statusBars = {}
    table.insert(self.statusBars, self.ScoringBar())
    self:scanKeeps()

    --Add events
    EVENT_MANAGER:RegisterForUpdate("CyrHUDKeepCheck", 5000, function()
        self:scanKeeps()
        self:updateAll()
    end)
    EVENT_MANAGER:RegisterForUpdate("CyrHUDUIUpdate", 1000, function()
        self:printAll()
    end)
    EVENT_MANAGER:RegisterForEvent("CyrHUDAttackChange", EVENT_KEEP_UNDER_ATTACK_CHANGED, self.eventAttackChange)
    self.visible = true

    EVENT_MANAGER:RegisterForEvent('CyrHUD', EVENT_ACTION_LAYER_POPPED, self.actionLayerChange)
    EVENT_MANAGER:RegisterForEvent('CyrHUD', EVENT_ACTION_LAYER_PUSHED, self.actionLayerChange)
end

function CyrHUD:disableQuestTrackers()
    self.trackers = {}
    if self.cfg.trackerDisable then
        if WYK_QuestTracker_MQT then
            self.trackers.WYK_QuestTracker_MQT = WYK_QuestTracker_MQT:GetAlpha()
            WYK_QuestTracker_MQT:SetAlpha(0)
        end
    end
end

function CyrHUD:reEnableQuestTrackers()
    if self.trackers then
        for k,v in pairs(self.trackers) do
            if _G[k] then _G[k]:SetAlpha(v) end
        end
    end
end

function CyrHUD:deinit()
    self:reEnableQuestTrackers()
    EVENT_MANAGER:UnregisterForUpdate("CyrHUDKeepCheck")
    EVENT_MANAGER:UnregisterForUpdate("CyrHUDUIUpdate")
    EVENT_MANAGER:UnregisterForUpdate("CyrHUDUpdateAPCount")
    EVENT_MANAGER:UnregisterForEvent("CyrHUD", EVENT_ACTION_LAYER_POPPED)
    EVENT_MANAGER:UnregisterForEvent("CyrHUD", EVENT_ACTION_LAYER_PUSHED)
    CyrHUD_UI:SetHidden(true)
    self.visible = false
end


function CyrHUD.toggle()
    local self = CyrHUD
    if self.visible then
        self:deinit()
    else
        self:init()
    end
end
--TODO: Properly setup on Addon init or playerLoad
--TODO: only show while in Cyrodiil?
SLASH_COMMANDS["/cyrhud"] = CyrHUD.toggle

function CyrHUD.playerInit()
    local self = CyrHUD
    if not self.initLAM then
        --Create UI
        self.ui = WINDOW_MANAGER:CreateTopLevelWindow("CyrHUD_UI")
        self.ui:SetWidth(280)
        self.ui:SetResizeToFitDescendents(true)
        self.ui:SetMouseEnabled(true)
        self.ui:SetMovable(true)
        self.ui:SetClampedToScreen(true)
        self.ui:SetHandler("OnMoveStop", self.saveWindowPosition)
        --Create settings menu
        local LAM = LibStub("LibAddonMenu-2.0")
        LAM:RegisterAddonPanel("CyrHUD-LAM", self.menuPanel)
        LAM:RegisterOptionControls("CyrHUD-LAM", self.menuOptions)
        self.initLAM = true

        --Init saved variables
        local def = {
            xoff = -10,
            yoff = 60,
            trackerDisable = false,
            showPopBars = false,
        }
        self.cfg = ZO_SavedVars:NewAccountWide("CyrHUD_SavedVars", 1.0, "config", def)
    end

    if IsPlayerInAvAWorld() then
        if not self.visible then
            self:init()
        end
    elseif self.visible then
        self:deinit()
    end
end

EVENT_MANAGER:RegisterForEvent("CyrHUD-init", EVENT_PLAYER_ACTIVATED, CyrHUD.playerInit)