-- 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.

-- Description: bios装备定制化
local log = require 'mc.logging'
local customize_cfg = {}

local BMC_CONFIG = "BMCBiosConfig"
local BOOTOPTION_CONFIG = "BootOption"
local SMBIOS_CONFIG = "SmBios"
local CUSTOM_SEETINGS = "CustomSettings"
local bios_factory = require 'factory.bios_factory'

local SYSTEM_ID<const> = 'SystemId'

local bios_config_key = {
    ["BMCSet_BootDevice"] = "StartOption",
    ["BMCSet_BootEffectMode"] = "StartOptionFlag"
}

local trans_user_map ={
    ['BMCSet_BootDevice'] = {
        [0] = 'No Override',
        [1] = 'PXE',
        [2] = 'Hard Drive',
        [3] = 'DVD-ROM',
        [4] = 'BIOS Setup',
        [15] = 'FDD/Removable Device'
    },
    ['BMCSet_BootEffectMode'] = {
        [1] = 'One-time',
        [2] = 'Permanent'
    }
}

-- 判断是否包含list中的定制项
local function config_in_list(config_table, config_key)
    return config_table[config_key]
end

local function get_system_in_list(system_id, config)
    for _, config_obj in pairs(config) do
        if config_obj[SYSTEM_ID].Value == system_id then
            return config_obj
        end
    end
    return nil
end

local function multihost_adapter_config(config_table, config_key, export_import_key)
    local bios_service = bios_factory.get_service('bios_service')
    if not bios_service then
        log:error("[bios]import bios config: bios service is nil")
        return
    end

    if not config_table[BMC_CONFIG] then
        config_table[BMC_CONFIG] = {}
    end

    for _, obj in pairs(bios_service:get_all_objs()) do
        local system_id = obj.system_id
        local bmc_config
        local system_config = get_system_in_list(system_id, config_table[BMC_CONFIG])
        if not system_config then
            bmc_config = {
                [SYSTEM_ID] = {
                    ['Value'] = system_id
                }
            }
            table.insert(config_table[BMC_CONFIG], bmc_config)
        else
            bmc_config = system_config
        end
        if not bmc_config[BOOTOPTION_CONFIG] then
            bmc_config[BOOTOPTION_CONFIG] = {}
        end
        if not bmc_config[SMBIOS_CONFIG] then
            bmc_config[SMBIOS_CONFIG] = {}
        end
        if not bmc_config[BOOTOPTION_CONFIG][export_import_key] then
            bmc_config[BOOTOPTION_CONFIG][export_import_key] = {}
        end
        for k, v in pairs(config_table[CUSTOM_SEETINGS][config_key]) do
            if k == 'Value' then
                bmc_config[BOOTOPTION_CONFIG][export_import_key][k] = trans_user_map[config_key][v]
                log:notice("system_id(%s) import(%s) customize(%s) setting to (%s : %s) successfully",
                    system_id, config_key, export_import_key, v, trans_user_map[config_key][v])
            else
                bmc_config[BOOTOPTION_CONFIG][export_import_key][k] = v
            end
        end
    end
end

local function adapter_config(config_table, config_key, export_import_key)
    if not config_table[BMC_CONFIG] then
        config_table[BMC_CONFIG] = {}
    end
    if not config_table[BMC_CONFIG][BOOTOPTION_CONFIG] then
        config_table[BMC_CONFIG][BOOTOPTION_CONFIG] = {}
    end
    if not config_table[BMC_CONFIG][SMBIOS_CONFIG] then
        config_table[BMC_CONFIG][SMBIOS_CONFIG] = {}
    end
    if not config_table[BMC_CONFIG][BOOTOPTION_CONFIG][export_import_key] then
        config_table[BMC_CONFIG][BOOTOPTION_CONFIG][export_import_key] = {}
    end

    for k, v in pairs(config_table[CUSTOM_SEETINGS][config_key]) do
        if k == 'Value' then
            config_table[BMC_CONFIG][BOOTOPTION_CONFIG][export_import_key][k] = trans_user_map[config_key][v]
            log:notice("import(%s) customize(%s) setting to (%s : %s) successfully",
                config_key,  export_import_key, v, trans_user_map[config_key][v])
        else
            config_table[BMC_CONFIG][BOOTOPTION_CONFIG][export_import_key][k] = v
        end
    end
end

-- 将BMCSet_BootDevice  ->  StartOptions
-- 将BMCSet_BootEffectMode  -> StartOptionFlag
function customize_cfg.config_import_data(config_table, is_multihost)
    if not config_table or not config_table[CUSTOM_SEETINGS] then
        return
    end
    for config_key, export_import_key in pairs(bios_config_key) do
        if config_in_list(config_table[CUSTOM_SEETINGS], config_key) then
            if is_multihost then
                multihost_adapter_config(config_table, config_key, export_import_key)
            else
                adapter_config(config_table, config_key, export_import_key)
            end
        end
    end
end

local function copy_config(config_table, config_key, export_import_key, config)
    if not config_table[CUSTOM_SEETINGS] then
        config_table[CUSTOM_SEETINGS]= {}
    end
    config_table[CUSTOM_SEETINGS][config_key] = {}
    local value = config[BOOTOPTION_CONFIG][export_import_key]
    for k, v in pairs(trans_user_map[config_key]) do
        if v == value then
            config_table[CUSTOM_SEETINGS][config_key] = k
            log:notice("export(%s) customize(%s) successfully, value is(%s : %s)",
                config_key,  export_import_key, k, v)
        end
    end
end

-- 将 StartOptions  ->  BMCSet_BootDevice  
-- 将 StartOptionFlag -> BMCSet_BootEffectMode
function customize_cfg.config_export_data(config_table, is_multihost)
    if not config_table or not config_table[BMC_CONFIG] then
        return
    end
    local config = config_table[BMC_CONFIG]
    if is_multihost then
        config = config_table[BMC_CONFIG][1]
    end
    for config_key, export_import_key in pairs(bios_config_key) do
        if config_in_list(config[BOOTOPTION_CONFIG], export_import_key) then
            copy_config(config_table, config_key, export_import_key, config)
        end
    end
end

return customize_cfg