-- 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 hddbackplane_data_keeping = class()

function hddbackplane_data_keeping:ctor(bus)
    self.bus = bus
    self.loaded_hdd_backplanes = {}
    self.hdd_backplane_path_name_map = {}
    self.intf = 'bmc.kepler.Systems.Board'
end

function hddbackplane_data_keeping:init()
end

function hddbackplane_data_keeping:get_all_infos()
    client:ForeachBoardObjects(function (obj)
        if string.find(obj.path, 'HddBackplane') then -- 通过路径包含来判断是否是硬盘背板
            self:hdd_backplane_added_callback(obj.path, obj.Name)
        end
    end)
end

function hddbackplane_data_keeping:hdd_backplane_added_callback(path, hdd_backplane_name)
    if self.hdd_backplane_path_name_map[path] then
        log:error("Duplicated hdd backplane obj(path:%s)", path)
        return
    end

    self.hdd_backplane_path_name_map[path] = hdd_backplane_name

    self.loaded_hdd_backplanes[hdd_backplane_name] = (not self.loaded_hdd_backplanes[hdd_backplane_name]) and
        1 or (self.loaded_hdd_backplanes[hdd_backplane_name] + 1)

    log:notice("Add hdd backplane obj(path:%s), name: %s, cur number:%u",
        path, hdd_backplane_name, self.loaded_hdd_backplanes[hdd_backplane_name])
end

-- hdd backplane对象添加回调
function hddbackplane_data_keeping:interface_added_callback(sender, path, interfaces_and_properties)
    local props_t = interfaces_and_properties[self.intf]
    if not props_t or not string.find(path, 'HddBackplane') then
        return
    end

    self:hdd_backplane_added_callback(path, props_t.Name:value())
end

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

function hddbackplane_data_keeping:interface_removed_process(sender, path, interface)
    if self.intf ~= interface or not string.find(path, 'HddBackplane') then
        log:debug("Current interface :%s", tostring(interface))
        return
    end

    if not self.hdd_backplane_path_name_map[path] then
        log:error("Hdd backplane obj(path:%s) not in table", path)
        return
    end

    local hdd_backplane_name = self.hdd_backplane_path_name_map[path]

    self.hdd_backplane_path_name_map[path] = nil

    if self.loaded_hdd_backplanes[hdd_backplane_name] >= 1 then
        self.loaded_hdd_backplanes[hdd_backplane_name] = self.loaded_hdd_backplanes[hdd_backplane_name] - 1
    else
        log:error("The number of hdd backplane obj(name:%s) less then 1", hdd_backplane_name)
    end

    log:notice("Delete hdd backplane obj(path:%s), cur number:%u", path,
        self.loaded_hdd_backplanes[hdd_backplane_name])
end

function hddbackplane_data_keeping:is_hdd_backplane_loaded(name)
    return self.loaded_hdd_backplanes[name] and self.loaded_hdd_backplanes[name] > 0
end

return hddbackplane_data_keeping