-- 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 defs = require 'domain.defs'
local singleton = require 'mc.singleton'
local log = require 'mc.logging'
local monitor = class()

-- 低8bit位为1
local DEFAULT_ERR_CODE<const> = (1 << 8) - 1

local OFFSET_OBJECT_MANAGEMENT<const> = 0  -- 分发对象&内部管理
local OFFSET_MDIO_REGISTER<const> = 1  -- lsw、phy mdio方法注册
local OFFSET_LSW_MDIO_RW<const> = 2  -- lsw mdio读写&驱动管理
local OFFSET_SMC_WRITE<const> = 3  -- smc命令字写入
local OFFSET_EXT_VLAN_CONFIG<const> = 4  -- 外网vlan配置
local OFFSET_PHY_MDIO_RW<const> = 5  -- phy mdio读写
local OFFSET_NEGOTIATION<const> = 6  -- 端口自协商配置
local OFFSET_FINISH<const> = 7  -- 预留

local net_config_description = {
    [0] = 'start',
    [1] = 'distribution object',
    [2] = 'logical chain building',
    [3] = 'bus initialization',
    [4] = 'update oem type',
    [5] = 'lsw hard reset',
    [6] = 'lsw initialization',
    [7] = 'port initialization',
    [8] = 'port isolation',
    [9] = 'port storm suppression',
    [10] = 'vlan initialization',
    [11] = 'vlan configuration',
    [12] = 'pvid configuration',
    [13] = 'extranet vlan configuration',
    [14] = 'lsw soft reset',
    [15] = 'phy hard reset',
    [16] = 'update phy type',
    [17] = 'phy initialization',
    [18] = 'auto-negotiation configuration',
    [19] = 'finish'
}

local err_code_offset = {
    [0] = OFFSET_OBJECT_MANAGEMENT,
    [1] = OFFSET_OBJECT_MANAGEMENT,
    [2] = OFFSET_OBJECT_MANAGEMENT,
    [3] = OFFSET_MDIO_REGISTER,
    [4] = OFFSET_LSW_MDIO_RW,
    [5] = OFFSET_SMC_WRITE,
    [6] = OFFSET_LSW_MDIO_RW,
    [7] = OFFSET_LSW_MDIO_RW,
    [8] = OFFSET_LSW_MDIO_RW,
    [9] = OFFSET_LSW_MDIO_RW,
    [10] = OFFSET_LSW_MDIO_RW,
    [11] = OFFSET_LSW_MDIO_RW,
    [12] = OFFSET_LSW_MDIO_RW,
    [13] = OFFSET_EXT_VLAN_CONFIG,
    [14] = OFFSET_LSW_MDIO_RW,
    [15] = OFFSET_SMC_WRITE,
    [16] = OFFSET_PHY_MDIO_RW,
    [17] = OFFSET_PHY_MDIO_RW,
    [18] = OFFSET_NEGOTIATION,
    [19] = OFFSET_FINISH
}

function monitor:ctor()
end

function monitor:init()
    self:init_state()
end

-- index: 配网阶段; res: 配网结果
function monitor:update_state(index, res)
    -- 更新配网状态为finish后只在重新配网时才会更新
    if self.config_state_idx == defs.NetConfigIdx.Finish then
        return
    end

    self.config_state_idx = index
    if res then
        log:debug('[lsw] update config state, %s success', net_config_description[index])
        return
    end

    -- 当前bit位由1置0时，打印错误信息
    if (1 << err_code_offset[index]) & self.config_err_code ~= 0 then
        local err_message = string.format('[lsw] update config state, %s failed', net_config_description[index])
        log:error(err_message)
        -- 网络配置异常会导致bmc不通，通过print在串口打印
        print(err_message)
    end
    -- 失败时将对应index的bit位置为0
    self.config_err_code = DEFAULT_ERR_CODE ~ (1 << err_code_offset[index]) & self.config_err_code
end

function monitor:call_config(index, func, ...)
    local res = func(...)
    self:update_state(index, res)
    return res
end

function monitor:get_config_state()
    return net_config_description[self.config_state_idx]
end

function monitor:get_config_errcode()
    return self.config_err_code
end

function monitor:init_state()
    self.config_state_idx = defs.NetConfigIdx.Start
    self.config_err_code = DEFAULT_ERR_CODE
end

return singleton(monitor)
