-- 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 bios_enum = require 'bios.types.enums'
local prop_def = require "macros.property_def"
local utils = require 'mc.utils'
local class = require 'mc.class'
local file_util = require 'infrastructure.file_util'
local bs_util = require 'util.base_util'
local utils_core = require 'utils.core'
local skynet = require 'skynet'

local smbios_object = class()

-- 向前兼容，当sys_id为1时，先获取SmBios_1的数据，如果没有则使用SmBios的数据创建新数据
local function get_smbios_info_table(db, sys_id)
    local db_id = 'SmBios'
    if sys_id ~= prop_def.DEFAULT_SYSTEM_ID then
        db_id = 'SmBios_' .. sys_id
    end
    local db_info = db:select(db.SmBiosInfoTable)
        :where(db.SmBiosInfoTable.Id:eq(db_id)):first()
    if db_info then
        if not db_info.SmBiosUpdatedFlag then
            db_info.SmBiosUpdatedFlag = 0
            db_info:save()
        end
        return db_info
    end
    local new_db_info = db.SmBiosInfoTable({Id = db_id,
        Version = '',
        SKUNumber = '',
        Family = '',
        SmBiosUpdatedFlag = 0,
        SmBiosStatus = 0})
    new_db_info:save()
    return new_db_info
end

local function get_private_obj()
    return {
        bios_id = 0x0,
        manu_id = 0xDB0700
    }
end

local function create_default_obj(smbios_gen_obj)
    if smbios_gen_obj then
        return smbios_gen_obj
    end
    local default_smbios_obj = {
        SystemId = 0,
        SerialNumber = 0,
        Version = 0,
        SKUNumber = 0,
        Family = 0,
        SmBiosStatus = 0,
        SmBiosUpdatedFlag = 0,
        FileChange = 0,
        FileName = '',
        DiffFileName = ''
    }
    return default_smbios_obj
end

local function get_smbios_info(smbios_db_obj, sys_id, smbios_gen_obj)
    local obj = create_default_obj(smbios_gen_obj)
    obj.SerialNumber = ''
    obj.FileChange = bios_enum.FileChange.SMBIOS_FILE_NO_CHANGE:value()
    obj.FileName = bs_util.get_data_path(sys_id, prop_def.SMBIOS_CONF_FILE)
    obj.DiffFileName = bs_util.get_data_path(sys_id, prop_def.SMBIOS_DIFF_FILE)
    if smbios_db_obj then
        obj.Version = smbios_db_obj.Version
        obj.SKUNumber = smbios_db_obj.SKUNumber
        obj.Family = smbios_db_obj.Family
        obj.SmBiosUpdatedFlag = smbios_db_obj.SmBiosUpdatedFlag
        obj.SmBiosStatus = smbios_db_obj.SmBiosStatus
    end

    return obj
end

local function smbios_recover(smbios_obj, db, sys_id)
    if sys_id ~= prop_def.DEFAULT_SYSTEM_ID then
        utils.mkdir_with_parents(prop_def.BIOS_CONFIG_PATH .. '/' .. sys_id,
            utils.S_IRWXU | utils.S_IRGRP | utils.S_IXGRP)
    end
    smbios_obj.db_obj = get_smbios_info_table(db, sys_id)
end

-- 申请资源 资源上树 获取资源
function smbios_object:ctor(db, sys_id, smbios_gen_obj)
    smbios_recover(self, db, sys_id)
    self.smbios_info = get_smbios_info(self.db_obj, sys_id, smbios_gen_obj)
    self.private_obj = get_private_obj()
end

function smbios_object:get_smbios_obj()
    return self.smbios_info
end

function smbios_object:get_manu_id()
    return self.private_obj.manu_id
end

function smbios_object:get_bios_id()
    return self.private_obj.bios_id
end

function smbios_object:update_smbios_status(smbios_status)
    local status = smbios_status:value()
    self.smbios_info.SmBiosStatus = status
    if self.db_obj and self.db_obj['SmBiosStatus'] then
        self.db_obj['SmBiosStatus'] = status
        self.db_obj:save()
    end
end

function smbios_object:update_smbios_updated_flag(smbios_update_flag)
    local flag = smbios_update_flag:value()
    self.smbios_info.SmBiosUpdatedFlag = flag
    if self.db_obj and self.db_obj['SmBiosUpdatedFlag'] then
        self.db_obj['SmBiosUpdatedFlag'] = flag
        self.db_obj:save()
    end
end

function smbios_object:get_smbios_updated_flag()
    return self.smbios_info.SmBiosUpdatedFlag
end

function smbios_object:get_smbios_file_name()
    return self.smbios_info.FileName
end

function smbios_object:get_smbios_file_change()
    return self.smbios_info.FileChange
end

function smbios_object:update_smbios_file_change(file_change)
    self.smbios_info.FileChange = file_change:value()
end

function smbios_object:get_prop(prop)
    return self.smbios_info[prop]
end

function smbios_object:set_prop(prop, value)
    self.smbios_info[prop] = value
    if self.db_obj and self.db_obj[prop] then
        self.db_obj[prop] = value
        self.db_obj:save()
    end
end

function smbios_object:collect_json_file(path)
    file_util.copy_file(self:get_smbios_file_name(), path .. '/' .. prop_def.SMBIOS_CONF_FILE)
    utils_core.chmod_s(path .. '/' .. prop_def.SMBIOS_CONF_FILE, utils.S_IRUSR | utils.S_IRGRP)
end

function smbios_object:get_dump_info()
    local props = self.smbios_info:get_all_prop_names()
    local log_info = {}
    table.insert(log_info, '------Smbios tree Begin------\r\n')
    local info
    for _, prop in pairs(props) do
        info = string.format('%s:%s', prop, bs_util.dump_prop(prop, self.smbios_info[prop]))
        table.insert(log_info, info)
        table.insert(log_info, '\r\n')
        skynet.sleep(10)
    end
    return table.concat(log_info)
end

return smbios_object