-- 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.
--         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 c_object = require 'mc.orm.object'
local skynet = require 'skynet'
local log = require 'mc.logging'

local c_storage_config = c_object('StorageConfig')
local c_controller = c_object('Controller')
local c_nvme = c_object('Nvme')
local c_drive = c_object('Drive')
local c_virtual_vpd_connect = c_object('VirtualVPDConnect')
local c_drive_info_table = c_object('DriveInfoTable')
local c_drives_table_info = c_object('DrivesTableInfo')
local c_global_storage_config_table = c_object('GlobalStorageConfigTable')
local c_volume = c_object('Volume')
local c_diskarray = c_object('DiskArray')
local c_storage_setting = c_object('StorageSetting')

-- 0xFE：待 PSR 更新，需轮询等待背板 StartSlot 稳定；0xFF：仅 CSR 生效，不等待直接上树
local START_SLOT_WAIT_PSR <const> = 0xFE
local DRIVE_WAIT_START_SLOT_INTERVAL <const> = 100   -- 轮询间隔 (skynet.sleep 单位)
local DRIVE_WAIT_START_SLOT_TIMEOUT <const> = 3000   -- 超时轮询次数，约 30s

function c_storage_config.create_mdb_object(value)
    return value
end

function c_controller.create_mdb_object(value)
    return value
end

function c_nvme.create_mdb_object(value)
    return value
end

function c_drive.create_mdb_object(value)
    return value
end

--- Drive 对象 before_add_object：仅在 HddBackplaneStartSlot=0xFE 时等待，稳定后更新 Id/Name/NodeId。
--- 0xFE：待 PSR 更新，轮询等待背板 StartSlot 稳定；0xFF：仅 CSR 生效，不等待直接上树并按当前值计算 Id/Name/NodeId。
---@param base_obj table MDB 下发的 Drive 对象（具 HddBackplaneStartSlot、RelativeSlot 等属性）
---@return boolean 是否允许上树，true 表示允许
function c_drive.before_add_object(base_obj)
    local start_slot = base_obj.HddBackplaneStartSlot
    if start_slot ~= START_SLOT_WAIT_PSR then
        return true
    end
    local wait_count = 0
    -- 仅当 0xFE（待 PSR 更新）时等待；0xFF 或 nil 不等待，后面用 0 兜底
    while start_slot == START_SLOT_WAIT_PSR do
        if wait_count >= DRIVE_WAIT_START_SLOT_TIMEOUT then
            log:info('[Drive before_add_object] timeout waiting HddBackplaneStartSlot, use 0, ObjectName=%s',
                base_obj.ObjectName or '')
            return
        end
        skynet.sleep(DRIVE_WAIT_START_SLOT_INTERVAL)
        start_slot = base_obj.HddBackplaneStartSlot
        wait_count = wait_count + 1
    end

    local rel = base_obj.RelativeSlot
    local id = start_slot + rel
    base_obj.Id = id
    base_obj.Name = string.format('Disk%d', id)
    base_obj.NodeId = string.format('HDDPlaneDisk%d', id)
    return true
end

function c_virtual_vpd_connect.create_mdb_object(value)
    return value
end

function c_drive_info_table.create_mdb_object(value)
    return value
end

function c_drives_table_info.create_mdb_object(value)
    return value
end

function c_global_storage_config_table.create_mdb_object(value)
    return value
end

function c_volume.create_mdb_object(value)
    return value
end

function c_diskarray.create_mdb_object(value)
    return value
end

function c_storage_setting.create_mdb_object(value)
    return value
end