-- 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 singleton = require 'mc.singleton'
local log = require 'mc.logging'
local cjson = require 'cjson'

local fru_persistence = {}
fru_persistence.__index = fru_persistence

function fru_persistence.new(db, local_db)
    fru_persistence.objs = {}
    fru_persistence.capas = {}
    fru_persistence.db = db
    fru_persistence.local_db = local_db

    return setmetatable({}, fru_persistence)
end

-- 将db中的数据同步资源树
function fru_persistence:sync_db2dbus(fru_id)
    local data = self.db:select(self.db.PersistentInformation):
        where(self.db.PersistentInformation.FruId:eq(fru_id)):first()
    if not data then
        log:info('Frudata(%d) persistent data is empty', fru_id)
        return nil, nil
    end

    log:notice('Frudata(%d) sync persistence db to dbus', fru_id)
    return cjson.decode(data.PersistentName), cjson.decode(data.PersistentValue)
end

-- 删除持久化数据
function fru_persistence:delete_db_raw(fru_id)
    local ok, ret = pcall(function()
        self.db:delete(self.db.PersistentInformation):where({ FruId = fru_id }):exec()
    end)
    if not ok then
        log:error('delete PersistentInformation [FruId:%s] from table [t_persistence_info] failed, error is %s.',
            fru_id, tostring(ret))
    end
end

-- 数据持久化，保存在数据库中
function fru_persistence:add(fru_id, property_name, value)
    -- 将数组转换为json字符串，节省空间
    local name_json = cjson.encode(property_name)
    local value_json = cjson.encode(value)

    local ok, ret = pcall(function ()
        local persistence_obj = self.db.PersistentInformation({ FruId = fru_id })
        persistence_obj.PersistentName = name_json
        persistence_obj.PersistentValue = value_json
        persistence_obj:save()
    end)

    if not ok then
        log:error('db insert PersistentInformation [FruId:%s] to table [t_persistence_info] failed, error is %s.',
            fru_id, tostring(ret))
        return
    end
    log:notice("Insert PersistentInformation [FruId:%s] to table [t_persistence_info]", fru_id)
end

function fru_persistence:insert_poweroff_data(id, prop, value)
    local t = self.local_db.tables['t_frudata_poweroff']
    local record = t({PerId = id, Key = prop})
    if next(record.__datas) then
        record.Value = value
    else
        record = t({PerId = id, Key = prop, Value = value})
    end
    record:save()
end

function fru_persistence:select_poweroff_data(id, prop)
    if not self.local_db then
        return  -- 兼容DT
    end
    local t = self.local_db.tables['t_frudata_poweroff']
    local record = self.local_db:select(t):where({PerId = id, Key = prop}):first()
    return record and record.Value
end

return singleton(fru_persistence)