/*
 * Copyright (c) 2025 Genexis B.V. All rights reserved.
 *
 * This Software and its content are protected by the Dutch Copyright Act
 * ('Auteurswet'). All and any copying and distribution of the software
 * and its content without authorization by Genexis B.V. is
 * prohibited. The prohibition includes every form of reproduction and
 * distribution.
 *
 */

import * as std from 'std';
import { isTrue } from '../utils.js';
import { getUciByType } from '../uci.js';


export function getDeviceBridgingBridgeStatus(bri) {
    const enable = _dm_get(`Device.Bridging.Bridge.${bri['.index']}.Enable`);
    return enable ? 'Enabled' : 'Disabled';
}

export function getDeviceBridgingBridgeSTPStatus(bri) {
    const stpState = std.loadFile(`/sys/class/net/${bri.Name}/bridge/stp_state`)?.trim();
    return stpState === '1' ? 'Enabled' : 'Disabled';
}

export function getDeviceBridgingBridgePortStatus(bri, port) {
    if (!port['.db']) return 'Up';

    const enable = _dm_get(`Device.Bridging.Bridge.${bri['.index']}.Port.${port['.index']}.Enable`);
    return enable ? 'Up' : 'Down';
}

export function getDeviceBridgingBridgePortLowerLayers(bri, port) {
    // Dynamic WiFi ports provide a resolved SSID reference directly.
    if (port && port.ssidPath) {
        return port.ssidPath;
    }

    const portPath = `Device.Bridging.Bridge.${bri['.index']}.Port.${port['.index']}`;

    const mgmtPort = _dm_get(`${portPath}.ManagementPort`);
    if (!isTrue(mgmtPort)) {
        return _dm_get(`${portPath}.LowerLayers`);
    }

    // For the management port, return a list of all other Port instances.
    const portBase = `Device.Bridging.Bridge.${bri['.index']}.Port.`;
    const ports = _dm_instances(portBase, undefined, 0);
    return ports.filter(p => p !== portPath).join(',');
}

export function infoDeviceBridgingBridgePort(path, port) {
    const mgmtPort = _dm_get(`${path}.ManagementPort`);
    if (typeof mgmtPort === 'undefined' || mgmtPort) return;

    const lower = _dm_get(`${path}.LowerLayers`);
    if (lower) {
        port.ifname = _dm_linker_value(lower);
    }
}

// Helper function to read network statistics
function getNetworkStat(port, statName) {
    return std.loadFile(`/sys/class/net/${port.ifname}/statistics/${statName}`)?.trim();
}

export const getDeviceBridgingBridgePortStatsBytesSent = (bri, port) =>
    getNetworkStat(port, 'tx_bytes');

export const getDeviceBridgingBridgePortStatsBytesReceived = (bri, port) =>
    getNetworkStat(port, 'rx_bytes');

export const getDeviceBridgingBridgePortStatsPacketsSent = (bri, port) =>
    getNetworkStat(port, 'tx_packets');

export const getDeviceBridgingBridgePortStatsPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_packets');

export const getDeviceBridgingBridgePortStatsErrorsSent = (bri, port) =>
    getNetworkStat(port, 'tx_errors');

export const getDeviceBridgingBridgePortStatsErrorsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_errors');

export const getDeviceBridgingBridgePortStatsDiscardPacketsSent = (bri, port) =>
    getNetworkStat(port, 'tx_dropped');

export const getDeviceBridgingBridgePortStatsDiscardPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_dropped');

export const getDeviceBridgingBridgePortStatsMulticastPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'multicast');

export const getDeviceBridgingBridgePortStatsUnicastPacketsSent = (bri, port) =>
    getNetworkStat(port, 'tx_unicast_packets');

export const getDeviceBridgingBridgePortStatsUnicastPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_unicast_packets');

export const getDeviceBridgingBridgePortStatsMulticastPacketsSent = (bri, port) =>
    getNetworkStat(port, 'tx_multicast_packets');

export const getDeviceBridgingBridgePortStatsBroadcastPacketsSent = (bri, port) =>
    getNetworkStat(port, 'tx_broadcast_packets');

export const getDeviceBridgingBridgePortStatsBroadcastPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_broadcast_packets');

export const getDeviceBridgingBridgePortStatsUnknownProtoPacketsReceived = (bri, port) =>
    getNetworkStat(port, 'rx_unknown_packets');

export function getDeviceBridgingBridgePort(bri) {
    const networkName = bri.Name.startsWith('br-') ? bri.Name.slice(3) : bri.Name;

    const wifiIfaces = getUciByType('wireless', 'wifi-iface', { match: { multi_ap: '2', network: networkName } });

    wifiIfaces?.forEach(x => {
        const ssid = getUciByType('WiFi', 'SSID',
            { match: { device: x.device, ssid: x.ssid}, confdir: '/etc/bbfdm/dmmap'});
        if (Array.isArray(ssid) && ssid[0].__instance__) {
            x.ssidPath = `Device.WiFi.SSID.${ssid[0].__instance__}`;
        }
    });

    return wifiIfaces;
}

export function setDeviceBridgingBridgePortManagementPort(val, bri, port) {
    if (isTrue(val)) {
        _db_set(`Device.Bridging.Bridge.${bri['.index']}.Port.${port['.index']}.Name`, bri.Name);
    }
    return 1;
}
