-- 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 class = require 'mc.class'
local execute_chain = require 'infrastructure.chain'
local bios_enum = require 'domain.bios_firmware.defs'
local executors = require 'domain.bios_firmware.package.executors.upgrade_executor'
local log = require 'mc.logging'

local UpgradeScenarios = class()

function UpgradeScenarios:ctor(upgrade_cfg)
    self.before_upgrade_chain = execute_chain.new()
    self.process_upgrade_chain = execute_chain.new()
    self.after_upgrade_chain = execute_chain.new()
    self.upgrade_cfg = upgrade_cfg
end

function UpgradeScenarios:build_before_chain()
    local before_steps = self.upgrade_cfg[bios_enum.UpgradePhrase.Before]
    for step, config in pairs(before_steps) do
        if executors[step] then
            local executor = executors[step].new(config or {})
            self.before_upgrade_chain:add(executor)
            log:notice('[bios]UpgradeScenarios: before chain add %s executor successfully', step)
        end
    end
end

function UpgradeScenarios:build_process_chain()
    local default_list = {
        [bios_enum.UpgradeSteps.PackageCheck] = 1,
        [bios_enum.UpgradeSteps.Backup] = 1,
        [bios_enum.UpgradeSteps.DecompressFile] = 1,
        [bios_enum.UpgradeSteps.ParserBin] = 1,
        [bios_enum.UpgradeSteps.SelectChannel] = 1,
        [bios_enum.UpgradeSteps.UpgradeComponent] = 1
    }
    local steps = bios_enum.UpgradeStepIndex
    for _, step in ipairs(steps) do
        local step_cfg = self.upgrade_cfg[bios_enum.UpgradePhrase.Process][step]
        if step_cfg or default_list[step] then
            local executor = executors[step].new(step_cfg or {})
            self.process_upgrade_chain:add(executor)
            log:notice('[bios]UpgradeScenarios: process chain add %s executor successfully', step)
        end
    end
end

function UpgradeScenarios:build_after_chain()
    local after_steps = self.upgrade_cfg[bios_enum.UpgradePhrase.After]
    for step, config in pairs(after_steps) do
        if executors[step] then
            local executor = executors[step].new(config or {})
            self.after_upgrade_chain:add(executor)
            log:notice('[bios]UpgradeScenarios: after chain add %s executor successfully', step)
        end
    end
end

function UpgradeScenarios:init()
    self:build_before_chain()
    self:build_process_chain()
    self:build_after_chain()
end

function UpgradeScenarios:execute_chain(chain, ctx)
    local err = chain:execute(ctx)
    if err then
        error(err)
    end
end

function UpgradeScenarios:execute(ctx)
    self:execute_chain(self.before_upgrade_chain, ctx)
    self:execute_chain(self.process_upgrade_chain, ctx)
    self:execute_chain(self.after_upgrade_chain, ctx)
end

return UpgradeScenarios