-- Copyright (c) 2025 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 class = require 'mc.class'
local bios_enum = require 'domain.bios_firmware.defs'
local vos = require 'utils.vos'
local bs_util = require 'util.base_util'
local skynet = require 'skynet'
local krun_firmware = require 'interface.mdb.krun_firmware'
local KrunFlash = class()

local function select_info_db(db, id)
    local db_info = db:select(db.KrunFirmware)
        :where(db.KrunFirmware.Id:eq(id)):first()
    if db_info then
        return db_info
    end
    local new_db_info = db.KrunFirmware({
        Id = id,
        Version = ''})
    new_db_info:save()
    return new_db_info
end

-- 升级包快照：包含升级包属性，是否异常中断等
function KrunFlash:ctor(bus, db, local_db, obj)
    self.bus = bus
    self.db = db
    self.local_db = local_db
    self.obj = obj
    self.block_chip = obj.RefChip
    self.flash_chip = obj.FlashChip
    self.Id = obj.Id
    self.UId = obj.UId
    self.Name = obj.Name
    self.RelatedSystems = obj.RelatedSystems
    self.firmware = krun_firmware.new(bus, db, self.Id, self.UId, self.RelatedSystems)
    local db_info = select_info_db(local_db, self.Id)
    self.db_info = db_info
    self.Version = db_info.Version
    self.PackageType = bios_enum.PackageType.Krun
    self.Period = bios_enum.PackagePeriod.Period3
    -- 缓存包路径
    self.CachePath = bs_util.get_krun_cached_path(self.Id)
end

function KrunFlash:init()
    self:update_activate_target_uid()
end

function KrunFlash:update_activate_target_uid()
    local param = bios_enum.KrunActiveRegisterList
    local uid_table = {}
    for uid in string.gmatch(param[8].Value, ',') do
        table.insert(uid_table, uid)
        if uid == self.UId then
            return
        end
    end
    table.insert(uid_table, self.UId)
    param[8].Value = table.concat(uid_table, ',')
end

function KrunFlash:check_uid_suitable(uid_list)
    for _, list_uid in pairs(uid_list) do
        if list_uid == self.UId then
            return true
        end
    end
    return false
end

function KrunFlash:_Persistence(prop, val)
    self[prop] = val
    if self.db_info[prop] ~= nil then
        self.db_info[prop] = val
        self.db_info:save()
    end
end

function KrunFlash:get_system_id()
    return self.RelatedSystems
end

function KrunFlash:include_system(system_id)
    for _, sys_id in pairs(self.RelatedSystems) do
        if system_id == sys_id then
            return true
        end
    end
    return false
end

function KrunFlash:set_prop(prop, value)
    self:_Persistence(prop, value)
end

function KrunFlash:get_prop(prop)
    return self[prop]
end

function KrunFlash:set_period(period)
    self:_Persistence('Period', period)
end

function KrunFlash:set_package_type(package_type)
    self:_Persistence('PackageType', package_type)
end

function KrunFlash:set_version(version)
    self:_Persistence('Version', version)
    skynet.fork_once(function ()
        self.firmware:update_krun_version(version)
    end)
end

function KrunFlash:set_cache_path(cache_path)
    self.CachePath = cache_path
end

function KrunFlash:get_cache_path()
    return self.CachePath
end

function KrunFlash:is_cache()
    return vos.get_file_accessible(self.CachePath)
end

function KrunFlash:get_version()
    return self.Version
end

function KrunFlash:get_krun_id()
    return self.Id
end

function KrunFlash:get_package_type()
    return self.PackageType
end

function KrunFlash:get_period()
    return self.Period
end

function KrunFlash:set_effective()
end

function KrunFlash:upgrade_start()
end

function KrunFlash:upgrade_finish()
end

return KrunFlash