-- Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
-- 
-- this file licensed under the 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 class = require 'mc.class'
local log = require 'mc.logging'
local client = require 'thermal_mgmt.client'

local cards_data_keeping = class()

function cards_data_keeping:ctor(bus)
    self.bus = bus
    self.loaded_pciecards = {}
    self.pciecard_path_name_map = {}
    self.intf = 'bmc.kepler.Systems.PCIeDevices.PCIeCard'
end

function cards_data_keeping:init()
end

function cards_data_keeping:get_all_infos()
    client:ForeachPCIeCardObjects(function (pciecard_obj)
        self:pciecard_added_callback(pciecard_obj.path, pciecard_obj.Name)
    end)
end

-- pciecard对象添加回调
function cards_data_keeping:pciecard_added_callback(path, pciecard_name)
    if self.pciecard_path_name_map[path] then
        log:error("Duplicated pciecard obj(path:%s)", path)
        return
    end

    self.pciecard_path_name_map[path] = pciecard_name

    self.loaded_pciecards[pciecard_name] =
        (not self.loaded_pciecards[pciecard_name]) and 1 or (self.loaded_pciecards[pciecard_name] + 1)

    log:notice("Add pciecard obj(path:%s), cur number:%u", path, self.loaded_pciecards[pciecard_name])
end

-- cards对象添加回调
function cards_data_keeping:interface_added_callback(sender, path, interfaces_and_properties)
    local props_t = interfaces_and_properties[self.intf]
    if not props_t then
        return
    end
    self:pciecard_added_callback(path, props_t.Name:value())
end

-- cards对象移除回调
function cards_data_keeping:interface_removed_callback(sender, path, interfaces)
    for _, intf in pairs(interfaces) do
        self:interface_removed_process(sender, path, intf)
    end
end

function cards_data_keeping:interface_removed_process(sender, path, interface)
    if interface ~= self.intf then
        return
    end
    if not self.pciecard_path_name_map[path] then
        log:error("Pciecard obj(path:%s) not in table", path)
        return
    end

    local pciecard_name = self.pciecard_path_name_map[path]

    self.pciecard_path_name_map[path] = nil

    if self.loaded_pciecards[pciecard_name] >= 1 then
        self.loaded_pciecards[pciecard_name] = self.loaded_pciecards[pciecard_name] - 1
    else
        log:error("The number of pciecard obj(name:%s) less then 1", pciecard_name)
    end

    log:notice("Delete pciecard obj(path:%s), cur number:%u", path, self.loaded_pciecards[pciecard_name])
end

function cards_data_keeping:is_pciecard_loaded(name)
    return self.loaded_pciecards[name] and self.loaded_pciecards[name] > 0
end

return cards_data_keeping