local T, C, L, _ = unpack(select(2, ...))

local _, ns = ...
local oUF = ns.oUF or oUF

local function FormatTime(time)
	if (time >= 86400) then
		return format('%dd', floor(time/86400 + 0.5))
	elseif (time>= 3600) then
		return format('%dh', floor(time/3600 + 0.5))
	elseif (time >= 60) then
		return format('%dm', floor(time/60 + 0.5))
	end

	return format('%d', math.fmod(time, 60))
end

local function RGBPercToHex(r, g, b)
    r = r <= 1 and r >= 0 and r or 1
    g = g <= 1 and g >= 0 and g or 1
    b = b <= 1 and b >= 0 and b or 1
    return format("%02x%02x%02x", r*255, g*255, b*255)
end

local utf8sub = function(string, i, dots)
    if not string then return end
    local bytes = string:len()
    if bytes <= i then
        return string
    else
        local len, pos = 0, 1
        while (pos <= bytes) do
            len = len + 1
            local c = string:byte(pos)
            if c > 0 and c <= 127 then
                pos = pos + 1
            elseif c >= 192 and c <= 223 then
                pos = pos + 2
            elseif c >= 224 and c <= 239 then
                pos = pos + 3
            elseif c >= 240 and c <= 247 then
                pos = pos + 4
            end
            if len == i then break end
        end
        if len == i and pos <= bytes then
            return string:sub(1, pos - 1)..(dots and "..." or "")
        else
            return string
        end
    end
end

oUF.Tags.Methods['dd:difficulty'] = function(u)
    local l = UnitLevel(u)
    return Hex(GetQuestDifficultyColor((l > 0) and l or 99))
end

oUF.Tags.Methods['dd:smarthp'] = function(u, r)
    local cur, max = UnitHealth(u), UnitHealthMax(u)
    if(not max) then return end
    if(max == 0) then max = 1 end

    if(not UnitIsConnected(r or u)) then
        return L.UNITFRAME_OFFLINE
    elseif(UnitIsGhost(u)) then
        return L.UNITFRAME_GHOST	
    elseif(UnitIsFeignDeath(u)) then
        return '|cffff3333FD|r'
    elseif(UnitIsDead(u)) then
        return L.UNITFRAME_DEAD
    else
        if(cur == max) then
            return '|cff98c290' .. T.ShortValue(max)
        else
            local r, g, b = ColorGradient(cur, max, 245/255, 68/255, 68/255, 245/255, 186/255, 69/255, 105/255, 201/255, 105/255)
            local color = Hex(r, g, b)
            return ('|cfffd5c69%s |cffdbf6db- %s%d%%|r'):format(T.ShortValue(cur), color, floor(cur/max*100))
        end
    end
end
oUF.Tags.Events['dd:smarthp'] = oUF.Tags.Events['missinghp']

oUF.Tags.Methods['dd:pp'] = function(u, r)
    local color = C.oUF_colors.power[select(2, UnitPowerType(u))]

    if color == nil then
        color = C.oUF_colors.power[select(1, UnitPowerType(u))]
    end

    return Hex(color[1], color[2], color[3]) .. T.ShortValue(UnitPower(u))
end
oUF.Tags.Events['dd:pp'] = 'UNIT_POWER UNIT_DISPLAYPOWER UNIT_MAXPOWER'

oUF.Tags.Methods['dd:realname'] = function(u, r)
    local name, realm = UnitName(r or u)
    if(realm) then
        name = name .. '-*'
    end

    if UnitIsAFK(r or u) then name = L.UNITFRAME_AFK .. name end
    if UnitIsDND(r or u) then name = L.UNITFRAME_DND .. name end

    return name
end
oUF.Tags.Events["dd:realname"] = "UNIT_NAME_UPDATE UNIT_CONNECTION PLAYER_FLAGS_CHANGED"

oUF.Tags.Methods["dd:raidname"] = function(unit, rolf)
    local color = { r = 1, g = 1, b = 1, }
    if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
        color = {r = 0.5, g = 0.5, b = 0.5}
    --[[elseif UnitIsPlayer(unit) then
        color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
    elseif UnitIsUnit(unit, "target") and UnitIsTapped("target") and not UnitIsTappedByPlayer("target") then
        color = {r = 0.5, g = 0.5, b = 0.5}]]--
    else
        --color = FACTION_BAR_COLORS[UnitReaction(unit, "player")]
        color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
    end

    local colorstr = color and RGBPercToHex(color.r,color.g,color.b) or "ffffff"
    local name = UnitName(rolf or unit)

    return "|cff"..colorstr..(utf8sub(name, 4, true) or "").."|r"
  end
oUF.Tags.Events["dd:raidname"] = "UNIT_NAME_UPDATE UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION"

oUF.Tags.Methods["dd:misshp"] = function(unit)
    local color = { r=1, g=1, b=1, }
    if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
        color = {r = 0.5, g = 0.5, b = 0.5}
    end
    local colorstr = color and RGBPercToHex(color.r,color.g,color.b) or "ffffff"

    local hpval
    if UnitIsDeadOrGhost(unit) then
        hpval = L.UNITFRAME_DEAD
    elseif not UnitIsConnected(unit) then
        hpval = L.UNITFRAME_OFFLINE
    else
        local max, min = UnitHealthMax(unit), UnitHealth(unit)
        if max-min > 0 then
            hpval = "-"..T.ShortValue(max-min)
        end
    end
    return "|cff"..colorstr..(hpval or "").."|r"
end
oUF.Tags.Events["dd:misshp"] = "UNIT_HEALTH UNIT_MAXHEALTH UNIT_CONNECTION"

oUF.Tags.Methods['dd:pvptimer'] = function(unit)
	if (not IsPVPTimerRunning() and GetPVPTimer() >= 0) then
		return ''
	end

	return FormatTime(math.floor(GetPVPTimer()/1000))
end

local instance, func, proxyfunc, proxy 
 
proxyfunc = function(self, ...)
    func(instance, ...)
    return proxy
end

proxy = setmetatable({
        done = function()
            return instance
        end,
    }, {
        __index = function(self, key)
            func = instance[key]
            return proxyfunc
        end,
    }
)

-- better tag api
function CreateTag(self, region, tagstr, frequentUpdates)
    if(type(region) == 'string') then
        region, tagstr = self, region
    end

    local fs = region:CreateFontString(nil, 'OVERLAY')
    fs:SetShadowColor(0, 0, 0)
    fs:SetShadowOffset(0.85, -0.85)

    if frequentUpdates then
        if type(frequentUpdates) == 'number' then
			fs.frequentUpdates = frequentUpdates
		else
			fs.frequentUpdates = .5
		end
    end

    self:Tag(fs, tagstr)

    instance = fs

    return proxy
end

oUF:RegisterMetaFunction('CreateTag', CreateTag)

