-- 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 log = require 'mc.logging'
local mdb_service = require 'mc.mdb.mdb_service'

local ODATA_ID <const> = "@odata.id"
local SYSTEM_ID<const> = 1
local OPTICALMODULE_INTERFACE <const> = "bmc.kepler.Systems.OpticalModule"
local NETWORKADAPTER_INTERFACE <const> = "bmc.kepler.Systems.NetworkAdapter"

local m = {}

local URL_MAP = {
    ['CPU']               = '/redfish/v1/Systems/%s/Processors/%s',
    ['PCIe GPU Card']     = '/redfish/v1/Systems/%s/Processors/%s',
    ['Memory']            = '/redfish/v1/Systems/%s/Memory/%s',
    ['Disk']              = '/redfish/v1/Chassis/1/Drives/%s',
    ['OpticalModule']     = '/redfish/v1/Chassis/1/NetworkAdapters/%s/NetworkPorts/%s/OpticalModule',
    ['PCIe NPU Card']     = '/redfish/v1/Chassis/1/PCIeDevices/%s',
    ['PCIe Storage Card'] = '/redfish/v1/Chassis/1/PCIeDevices/%s'
}

local function get_system_id()
    return SYSTEM_ID
end

local function get_optical_module_odata_id(obj, url_pattern)
    local filter = { SerialNumber = obj.SerialNumber }
    local ok, rsp = pcall(mdb_service.get_path, bus, OPTICALMODULE_INTERFACE, cjson.encode(filter), false)
    if not ok then
        log:info("Get OpticalModule path failed, err: %s.", rsp)
        return cjson.null
    end
    local port_id = string.match(rsp.Path, "NetworkPort_(%d+)_")
    local network_adapter_path = string.match(rsp.Path, "(.+)/Ports")
    ok, rsp = pcall(mdb.get_object, bus, network_adapter_path, NETWORKADAPTER_INTERFACE)
    if not ok then
        log:info("Get NetworkAdapter object failed, err: %s.", rsp)
        return cjson.null
    end
    return string.format(url_pattern, rsp.NodeId, tostring(port_id + 1))
end

local function get_odata_id(obj)
    local url_pattern = URL_MAP[obj.AssetType]
    local id
    if obj.AssetType == 'CPU' then
        id = string.match(obj.AssetName, '%d+')
        return string.format(url_pattern, get_system_id(), tostring(id))
    elseif obj.AssetType == 'Memory' then
        return string.format(url_pattern, get_system_id(), obj.AssetName)
    elseif obj.AssetType == 'Disk' then
        return string.format(url_pattern, 'HDDPlaneDisk' .. obj.Slot)
    elseif obj.AssetType == 'PCIe GPU Card' then
        id = string.match(obj.AssetName, '%d+')
        return string.format(url_pattern, get_system_id(), 'Gpu' .. tostring(id))
    elseif obj.AssetType == 'PCIe NPU Card' or obj.AssetType == 'PCIe Storage Card' then
        return string.format(url_pattern, 'PCIeCard' .. obj.Slot)
    elseif obj.AssetType == 'OpticalModule' then
        return get_optical_module_odata_id(obj, url_pattern)
    else
        return cjson.null
    end
end

function m.get_result(asset_list)
    if not asset_list or #asset_list == 0 then
        return {}
    end
    local res = cjson.json_object_ordered_decode(asset_list)
    local results = cjson.json_object_new_array()
    for i = 1, #res, 1 do
        local asset_item = cjson.json_object_new_object()
        local data_item = cjson.json_object_new_object()
        asset_item.Name = res[i].AssetName
        asset_item[ODATA_ID] = get_odata_id(res[i])
        data_item.AssetType = res[i].AssetType
        data_item.AssetTag = res[i].AssetTag
        data_item.SerialNumber = res[i].SerialNumber
        data_item.PartNumber = res[i].PartNumber
        data_item.PCBVersion = res[i].PCBVersion
        data_item.FirmwareVersion = res[i].FirmwareVersion
        data_item.Manufacturer = res[i].Manufacturer
        data_item.ManufactureDate = res[i].ManufactureDate
        asset_item.Data = data_item
        results[#results + 1] = asset_item
    end
    return results
end

return m
