local floor = math.floor
local assert = assert
local type = type
local util = require("tracing.util")
-- local skynet = require("skynet")
local setmetatable = setmetatable
-------------------------------------------------

local span_methods = {}
local span_mt = {
    __index = span_methods,
}

-- local messageColloctorAddr

local function new(operat_name, trace_id, parent_id, kind)
    kind = kind or "SERVER"
    local nowTime = util.get_timestamp()
    local span_id = util.generate_span_id(nowTime)
    if not trace_id then
        trace_id = span_id
    end
    assert(kind == "SERVER" or kind == "CLIENT", "invalid span kind")
    assert(type(operat_name) == "string" and operat_name ~= "", "invalid span name") -- 方法名
    assert(type(trace_id) == "string", "invalid trace id")
    assert(type(span_id) == "string", "invalid span id")
    if parent_id then
        assert(type(parent_id) == "string", "invalid parent id")
    end
    return setmetatable({
        kind = kind,
        traceId = trace_id,
        id = span_id,
        parentId = parent_id,
        name = operat_name,
        timestamp = nowTime,
        localEndpoint = {
            serviceName = SERVICE_NAME,
        },
    }, span_mt)
end

function span_methods:finish()
    assert(self.duration == nil, "span already finished")
    local duration = util.get_timestamp() - self.timestamp
    assert(duration >= 0, "invalid span duration")
    self.duration = floor(duration)
    -- TODO: xiaojin 增加 前缀
    -- self:set_tag("k", gKingdomID and tostring(gKingdomID))
    -- self:set_tag("m", gMapID and tostring(gMapID))
    -- self:set_tag("u", gUid and tostring(gUid))
    -- self:set_tag("p", tostring(skynet.self()))

    -- if not messageColloctorAddr then
    --     messageColloctorAddr = svrAddressMgr.getSvr(svrAddressMgr.messageCollectorService)
    -- end
    -- skynet.send(messageColloctorAddr, "lua", "sendMessage", TableUtil.cloneWithoutMeta(self))
    return true
end

function span_methods:set_tag(key, value)
    if not value then
        return false
    end
    assert(type(key) == "string", "invalid tag key must string")
    assert(type(value) == "string", "invalid tag value must string")

    local tags = self.tags
    if tags then
        tags[key] = value
    else
        tags = {
            [key] = value,
        }
        self.tags = tags
    end
    return true
end

return {
    new = new,
}
