-- 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 port_defs = require 'device.class.nic_mgmt.port.port_defs'
local c_network_port = require 'device.class.network_port'
local comm_fun = require 'device.class.nic_mgmt.comm_fun'
local comm_defs = require 'device.class.nic_mgmt.comm_defs'
local custom_messages = require 'messages.custom'
local context = require 'mc.context'
local log = require 'mc.logging'

local port_property_listen = {}

local property_changed_switch<const> = {
    LinkStatus = c_network_port.update_link_status,
    LinkStatusNumeric = c_network_port.synchronize_link_status,
    PermanentMACAddress = c_network_port.emit_mac_change_signal,
    MACAddress = c_network_port.emit_actual_mac_change_signal
}

local function set_lldp_tx_enabled(orm_obj, value, bus)
    log:notice('set lldp tx enabled for port %s, value is %s', orm_obj.NodeId, value)
    local ctx = context.get_context()

    local device_path = orm_obj.device_path
    if not device_path or device_path == '' then
        log:error('set lldp tx enabled failed for port %s, device_path is empty', orm_obj.NodeId)
        orm_obj:log_lldp_operation(value, ctx, false)
        error(custom_messages.ConfigPortLLDPErr())
    end

    local device_obj = comm_fun.get_device_obj_by_path_interface(bus, device_path,
        comm_defs.NETWORK_PORT_DEVICE_INTERFACE)
    if not device_obj then
        log:error('set lldp tx enabled failed for port %s, device_obj is nil', orm_obj.NodeId)
        orm_obj:log_lldp_operation(value, ctx, false)
        error(custom_messages.ConfigPortLLDPErr())
    end

    local ok, ret = pcall(function()
        return device_obj:call_method('SetLLDPTxEnable', 'b', value)
    end)
    if not ok then
        log:error('set lldp tx enabled failed for port %s, err is %s', orm_obj.NodeId, ret)
        orm_obj:log_lldp_operation(value, ctx, false)
        error(custom_messages.ConfigPortLLDPErr())
    end
    if not ret then
        log:error('set lldp tx enabled failed for port %s', orm_obj.NodeId)
        orm_obj:log_lldp_operation(value, ctx, false)
        error(custom_messages.ConfigPortLLDPErr())
    end

    log:notice('%s port %s lldp tx successfully', value and 'enable' or 'disable', orm_obj.NodeId)
    orm_obj:log_lldp_operation(value, ctx, true)
end

function port_property_listen.register_property_changed_callback(orm_obj, bus)
    local link_status = orm_obj.LinkStatusNumeric == 1 and 'Connected' or
        orm_obj.LinkStatusNumeric == 0 and 'Disconnected' or port_defs.INVALID_DATA_STRING
    orm_obj:set_link_status(link_status)
    orm_obj:connect_signal(orm_obj.on_property_changed, function(name, value)
        if property_changed_switch[name] then
            orm_obj:next_tick(property_changed_switch[name], orm_obj, value)
        end
    end)
    if orm_obj['bmc.kepler.Systems.NetworkPort'] then
        orm_obj:connect_signal(orm_obj['bmc.kepler.Systems.NetworkPort'].property_before_change, function(name, value)
            if name == 'LLDPEnabled' then
                set_lldp_tx_enabled(orm_obj, value, bus)
            end
        end)
    end
end

return port_property_listen