-- Copyright (c) 2024 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.

local cjson = require 'cjson'
local mc_utils = require 'mc.utils'

local COM_NODE_ID<const> = 'ComNodeId'
local SLOT_ID<const> = 'SlotId'
local TAG_INFO<const> = 'TagInfo'
local TAG_INFO_TYPE<const> = 'Type'
local ODATA_ID<const> = '@odata.id'
local IDENTIFICATIONS<const> = 'Identifications'
local PROPERTY_VALUE<const> = 'PropertyValue'
local PROPERTY_NAME<const> = 'PropertyName'
-- 数据采集服务返回的无效node_id
local INVALID_NODE_ID = 'NA'

local URL_MAP = {
    ['CPU']       = '/redfish/v1/Systems/%s/Processors/%s',
    ['Memory']    = '/redfish/v1/Systems/%s/Memory/%s',
    ['Disk']      = '/redfish/v1/Chassis/%s/Drives/%s',
    ['Fan']       = '/redfish/v1/Chassis/%s/Thermal#/Fans/%s',
    ['Mainboard'] = '/redfish/v1/Chassis/%s/Boards/chassisMainBoard',
    ['Chassis']   = '/redfish/v1/Chassis/%s',
    ['System']    = '/redfish/v1/Systems/%s',
    ['PSU']       = '/redfish/v1/Chassis/%s/Power#/PowerSupplies/%s',
    ['OpticalModule'] = '/redfish/v1/Chassis/1/NetworkAdapters/%s/NetworkPorts/%s',
    ['NPU']       = '/redfish/v1/Systems/%s/Processors/Npu%s'
}

local m = {}

local function set_odataid_by_type(data_instance, type)
    -- NodeId为NA时，只有Mainboard/Chassis/System类型有效（直接拼接slotid返回）；其余类型认为是无效ODataID
    local url_pattern = URL_MAP[type]
    if type == 'Mainboard' or type == 'Chassis' or type == 'System' then
        local slot_id = data_instance[SLOT_ID]
        data_instance[ODATA_ID] = string.format(url_pattern, slot_id)
    elseif type == 'OpticalModule' then
        for _, item in pairs(data_instance[TAG_INFO][IDENTIFICATIONS]) do
            if item[PROPERTY_NAME] == 'Location' then
                -- "EthernetAdapterBoard_PORT1"
                local locations = mc_utils.split(item[PROPERTY_VALUE], '_')
                local port_id = locations[2]:find('%d')
                data_instance[ODATA_ID] = string.format(url_pattern, locations[1], locations[2]:sub(port_id))
                break
            end
        end
    else
        data_instance[ODATA_ID] = cjson.null
    end
end

function m.get_deserialize_data(serialized_data)
    local data_table = cjson.decode(serialized_data)
    local node_id
    local info_type
    local url_pattern
    local slot_id
    for _, data_instance in pairs(data_table) do
        node_id = data_instance[COM_NODE_ID]
        info_type = data_instance[TAG_INFO][TAG_INFO_TYPE]
        -- replace ComNodeId with @odata.id
        if node_id == INVALID_NODE_ID then
            set_odataid_by_type(data_instance, info_type)
        else
            url_pattern = URL_MAP[info_type]
            slot_id = data_instance[SLOT_ID]
            data_instance[ODATA_ID] = string.format(url_pattern, slot_id, node_id)
        end
        -- remove keys
        data_instance[SLOT_ID] = nil
        data_instance[COM_NODE_ID] = nil
    end
    return data_table
end

function m.check_time(start_time, end_time)
    local s_time = tonumber(start_time)
    local e_time = tonumber(end_time)
    local current_time = mc_utils.time()
    if s_time == nil or e_time == nil then
        error(base_messages.QueryNotSupportedOnResource())
    end
    if e_time < 0 or e_time >= 2147483647 then
        error(base_messages.QueryNotSupportedOnResource())
    end
    if s_time < 0 or s_time >= 2147483647 then
        error(base_messages.QueryNotSupportedOnResource())
    end
    if s_time > e_time and e_time ~= 0 then
        error(base_messages.QueryNotSupportedOnResource())
    end
    if s_time > current_time.tv_sec then
        error(base_messages.QueryNotSupportedOnResource())
    end
    return true
end

return m
