local ADDON_NAME, ns = ...
local WF = ns.WF

WF.Token = WF.Token or {}
local Token = WF.Token

Token._callbacks = Token._callbacks or {}

local function Now()
  if GetServerTime then
    local ok, t = pcall(GetServerTime)
    if ok and type(t) == "number" then return t end
  end
  return time()
end

function Token:IsSupported()
  return (C_WowTokenPublic and C_WowTokenPublic.GetCurrentMarketPrice and C_WowTokenPublic.UpdateMarketPrice) and true or false
end

function Token:GetCached()
  if not (WF.DB and WF.DB.GetSetting) then
    return nil, nil
  end
  local p = WF.DB:GetSetting("tokenPrice")
  local ts = WF.DB:GetSetting("tokenUpdatedAt")
  return tonumber(p) or nil, tonumber(ts) or nil
end

function Token:_SetCached(price)
  if not (WF.DB and WF.DB.SetSetting) then return end
  WF.DB:SetSetting("tokenPrice", price)
  WF.DB:SetSetting("tokenUpdatedAt", Now())
end

function Token:RegisterCallback(fn)
  if type(fn) ~= "function" then return end
  self._callbacks[#self._callbacks + 1] = fn
end

function Token:_Fire()
  for i = 1, #self._callbacks do
    WF.Util:SafeCall(self._callbacks[i])
  end
end

function Token:PullNow()
  if not self:IsSupported() then return nil end

  local ok, price = pcall(C_WowTokenPublic.GetCurrentMarketPrice)
  if ok and type(price) == "number" and price > 0 then
    self:_SetCached(price)
    self:_Fire()
    return price
  end
  return nil
end

function Token:RequestUpdate()
  if not self:IsSupported() then return false end
  pcall(C_WowTokenPublic.UpdateMarketPrice)
  return true
end

function Token:Init()
  if self._inited then return end
  self._inited = true

  if not self:IsSupported() then
    return
  end

  if WF.Events and WF.Events.On then
    WF.Events:On("TOKEN_MARKET_PRICE_UPDATED", function()
      Token:PullNow()
    end)

    WF.Events:On("PLAYER_LOGIN", function()
      Token:RequestUpdate()
    end)
  else
    local f = CreateFrame("Frame")
    f:RegisterEvent("TOKEN_MARKET_PRICE_UPDATED")
    f:RegisterEvent("PLAYER_LOGIN")
    f:SetScript("OnEvent", function(_, event)
      if event == "TOKEN_MARKET_PRICE_UPDATED" then
        Token:PullNow()
      elseif event == "PLAYER_LOGIN" then
        Token:RequestUpdate()
      end
    end)
  end
end
