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

-- Description: 独立vrd管理

local log = require 'mc.logging'
local singleton = require 'mc.singleton'
local class = require 'mc.class'
local signal = require 'mc.signal'
local upgrade_subject = require 'upgrade_subject.upgrade_subject'
local cmn = require 'common'
local vrd_upgrade = require 'independent_vrd.chip.vrd_upgrade'

local ind_vrd_service = class()
ind_vrd_service.__index = ind_vrd_service

local function create_vrd_obj(object, pos)
    return {
        Id = "VRD_" .. object.BoardType .. "_" .. pos,
        BoardType = object.BoardType,
        RefChip = object.RefChip,
        LockChip = object.RefChip,
        UID = object.UID,
        SoftwareId = object.SoftwareId,
        Protocol = "SMC",
        MajorVersion = "",
        MinorVersion = "",
        Revision = "",
        SubCompList = {},
        object = object
    }
end

function ind_vrd_service:on_add_object(class_name, object, position)
    local switch = {
        ['VRDFirmware'] = function()
            local ok, chip_obj = pcall(require, string.format('independent_vrd.chip.%s', string.lower(object.ChipType)))
            if not ok or not chip_obj then
                log:error('invalid vrd chip type: %s', object.ChipType)
                return
            end

            local obj = chip_obj.new(create_vrd_obj(object, position), position, self.vrd_info_changed)
            obj:register_firmware_info(self.bus)
            table.insert(self.ind_vrd_collection, obj)
        end
    }

    if switch[class_name] then
        switch[class_name]()
        log:notice('[VRDFirmware] Add object, class: %s, position: %s, type: %s',
            class_name, position, object.ChipType)
    end
end

function ind_vrd_service:on_delete_object(class_name, object, position)
    local switch = {
        ['VRDFirmware'] = function ()
            cmn.remove_ele_by_position(self.ind_vrd_collection, position)
        end
    }

    if switch[class_name] then
        switch[class_name]()
        log:notice('[VRDFirmware] Delete object, class: %s, position: %s, type: %s',
            class_name, position, object.ChipType)
    end
end

function ind_vrd_service.new()
    return setmetatable({
        ind_vrd_collection = {}
    }, ind_vrd_service)
end

function ind_vrd_service:init(bus, db)
    self.bus = bus
    self.vrd_info_changed = signal.new()
    self.vrd_upgrade_obj = vrd_upgrade.new(bus, db, self.ind_vrd_collection)
    upgrade_subject.get_instance():register_upgrade_observer(self.vrd_upgrade_obj, 'Independent_Vrd')
    upgrade_subject.get_instance():register_active_observer(self.vrd_upgrade_obj, 'INDEPENDENT_VRD')
end

return singleton(ind_vrd_service)