-- 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 c_base = require 'ub_cable.class.base'
local log = require 'mc.logging'
local json = require 'cjson'

local c_inter_node_cable_configuration = class(c_base)

local function cfg_new(src_node_id, src_cpu_id, src_die_id, src_macro_id, src_interface_device_port_id,
    target_node_id, target_cpu_id, target_die_id, target_macro_id, target_interface_device_port_id)
    return {
        SrcNodeId = src_node_id,
        SrcCPUId = src_cpu_id,
        SrcDieId = src_die_id,
        SrcMacroId = src_macro_id,
        SrcPortId = src_interface_device_port_id,
        TargetNodeId = target_node_id,
        TargetCPUId = target_cpu_id,
        TargetDieId = target_die_id,
        TargetMacroId = target_macro_id,
        TargetPortId = target_interface_device_port_id
    }
end

function c_inter_node_cable_configuration:init_paired_cfg()
    pcall(function()
        local cfg, src_cfg, target_cfg
        if self.mds_obj.Configurations and #self.mds_obj.Configurations ~= 0 and
            #self.mds_obj.Configurations[1] ~= 0 then
            for i, config in ipairs(self.mds_obj.Configurations) do
                -- config 内容形式 [[1,0,0,2,1],[2,0,0,2,1]]
                src_cfg, target_cfg = table.unpack(config)
                cfg = cfg_new(src_cfg[1], src_cfg[2], src_cfg[3], src_cfg[4], src_cfg[5],
                    target_cfg[1], target_cfg[2], target_cfg[3], target_cfg[4], target_cfg[5])
                table.insert(self.paired_cfg, cfg)
            end
        end
    end)
end

function c_inter_node_cable_configuration:print_paired_cfg()
    for k, cfg in pairs(self.paired_cfg) do
        log:notice("print_paired_cfg %s is %s-%s-%s-%s-%s-%s-%s-%s", k, cfg.SrcNodeId, cfg.SrcDieId, cfg.SrcMacroId,
            cfg.SrcPortId, cfg.TargetNodeId, cfg.TargetDieId, cfg.TargetMacroId, cfg.TargetPortId)
    end
end

function c_inter_node_cable_configuration:init_src_target_map()
    local src_key
    for _, cfg in pairs(self.paired_cfg) do
        src_key = string.format("%s_%s_%s_%s", cfg.SrcNodeId, cfg.SrcDieId, cfg.SrcMacroId, cfg.SrcPortId)
        self.src_target_info_map[src_key] = {
            TargetNodeId = cfg.TargetNodeId,
            TargetDieId = cfg.TargetDieId,
            TargetMacroId = cfg.TargetMacroId,
            TargetPortId = cfg.TargetPortId
        }
        -- 对端反向添加配置
        src_key = string.format("%s_%s_%s_%s", cfg.TargetNodeId, cfg.TargetDieId, cfg.TargetMacroId, cfg.TargetPortId)
        self.src_target_info_map[src_key] = {
            TargetNodeId = cfg.SrcNodeId,
            TargetDieId = cfg.SrcDieId,
            TargetMacroId = cfg.SrcMacroId,
            TargetPortId = cfg.SrcPortId
        }
    end
end

function c_inter_node_cable_configuration:init()
    log:notice("c_inter_node_cable_configuration v=%s", json.encode(self.mds_obj.Configurations))
    self:init_paired_cfg()
    self:print_paired_cfg()
    self:init_src_target_map()
end

function c_inter_node_cable_configuration:ctor(mds_obj, position, bus)
    self.mds_obj = mds_obj
    self.position = position
    self.bus = bus
    self.paired_cfg = {}
    self.src_target_info_map = {} -- 白名单配置，key是本端信息字符串，value是对端信息
end

return c_inter_node_cable_configuration