-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
--- @class MetricParser
--- @field parse_metric_file function
--- @field parse_metric_text function
local MetricParser = {}

---
--- 是否包含在数组内, 如果table为空, 则返回false, 如果value为空, 则返回false
---
--- @param table table
--- @param value string
--- @return boolean
local function contains(table, value)
    for _, v in ipairs(table) do if v == value then return true end end
    return false
end

---
--- 解析单行数据
---
--- @param line string
--- @return string, string
local function parse_line(line)
    local key, value = line:match("^([^:]+):(.*)$")
    key = key and string.gsub(key, "^%s*(.-)%s*$", "%1") or nil
    value = value and string.gsub(value, "^%s*(.-)%s*$", "%1") or nil
    return key, value
end


local scope_keys = {"scope name", "schema url", "version"}
local instrument_keys = {
    "instrument name", "start time", "end time", "description", "unit", "type",
    "value", "attributes", "resources", "service.name", "telemetry.sdk.version",
    "telemetry.sdk.name", "telemetry.sdk.language", "sum"
}

---
--- 解析文本
---
--- @param text string
--- @return table, string
function MetricParser:parse_metric_text(text)
    local lines = {}
    for line in text:gmatch("[^\r\n]+") do
        local content = string.gsub(line, "^%s*(.-)%s*$", "%1")

        -- 跳过空行
        if content ~= "" then table.insert(lines, content) end
    end

    local result = {}
    local i = 1
    while i <= #lines do
        local line = lines[i]
        local metric = {}
        if line:match("^{") then
            metric.scope = {}
            metric.instruments = {}

            i = i + 1
            local instrument
            while i <= #lines do
                line = lines[i]
                if line:match("^}") then break end

                local key, value = parse_line(line)
                if contains(scope_keys, key) then
                    metric.scope[key] = value
                elseif contains(instrument_keys, key) then
                    instrument = instrument or {}
                    if key and instrument[key] then
                        table.insert(metric.instruments, instrument)
                        instrument = {}
                    end
                    instrument[key] = value
                end
                i = i + 1
            end

            if instrument then
                table.insert(metric.instruments, instrument)
            end

            table.insert(result, metric)
        end
        i = i + 1
    end

    return result
end

---
--- 解析整个文件
---
--- @param filename string
--- @return table, string
function MetricParser:parse_metric_file(filename)
    local file = io.open(filename, "r")
    if not file then return nil, "无法打开文件: " .. filename end

    local content = file:read("*all")
    file:close()
    return MetricParser:parse_metric_text(content)
end

return MetricParser
