/* 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.
 */
#define LUA_LIB

#define GNU_SOURCE /* See feature_test_macros(7) */
#include <errno.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <glib-2.0/glib.h>
#include <glib-2.0/glib/gstdio.h>
#include <secure/securec.h>
#include <lua.h>
#include <lauxlib.h>

#include "libncsi_protocol.h"
#include "logging.h"

static int l_ncsi_common_init(lua_State *L)
{
    ncsi_common_init();
    debug_log(DLOG_INFO, "[ncsi_protocol], ncsi common init trigger.");
    return 0;
}

static int l_ncsi_paramter_init(lua_State *L)
{
    gint32 ret;
    guint8 channel_id = luaL_checkinteger(L, 1);
    const gchar *eth_name =  luaL_checkstring(L, 2);
    guint8 state = luaL_checkinteger(L, 3);
    guint8 package_id;

    ret = ncsi_paramter_init(channel_id, eth_name, state, &package_id);

    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi paramter init trigger, channel_id=%u, eth_name=%s, state=%u, ret=%d, package_id=%u.",
        channel_id, eth_name, state, ret, package_id);
    lua_pushinteger(L, ret);
    lua_pushinteger(L, package_id);
    return 2; // 返回2个参数
}

static int l_ncsi_eth_mac_init(lua_State *L)
{
    gint32 ret;
    const gchar *eth_mac = (gchar *)luaL_checkstring(L, 1);

    ret = ncsi_eth_mac_init(eth_mac);
    debug_log(DLOG_INFO, "[ncsi_protocol], ncsi eth mac init trigger, ret=%d.", ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_receive_packet(lua_State *L)
{
    gint32 sock = luaL_checkinteger(L, 1);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 2);
    gint32 aen_oem_status = 0;
    if (sock < 0) {
        perror("socket");
        lua_pushinteger(L, NCSI_FALSE);
        lua_pushinteger(L, aen_oem_status);
        return 2;
    }

    ncsi_receive_packet(sock, eth_name, &aen_oem_status);

    lua_pushinteger(L, NCSI_OK);
    lua_pushinteger(L, aen_oem_status);
    return 2; // 返回2个参数
}

static int l_ncsi_get_link_status(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);
    guchar eth_id = luaL_checkinteger(L, 4);
    guchar link_status = 0;

    ret = ncsi_get_link_status(package_id, channel_id, eth_name);
    link_status = g_ncsi_parameter.lnk_stauts[eth_id][channel_id].link_flag;

    lua_pushinteger(L, ret);
    lua_pushinteger(L, link_status);
    return 2; // 返回2个参数
}

static int l_ncsi_send_cmd(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    guint8 packet_type = luaL_checkinteger(L, 3);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 4);

    ret = ncsi_send_cmd(package_id, channel_id, packet_type, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi send cmd trigger, package_id=%u, channel_id=%u, packet_type=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, packet_type, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_clear_initial_state(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_clear_initial_state(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi clear initial state trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_select_package(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 2);

    ret = ncsi_select_package(package_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi select package trigger, package_id=%u, eth_name=%s, ret=%d.",
        package_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_disable_channel(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_disable_channel(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi disable channel trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_enable_channel(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_enable_channel(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi enable channel trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_enable_brdcast_filter(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_enable_brdcast_filter(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi enable brdcast filter trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_disable_brdcast_filter(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_disable_brdcast_filter(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi disable brdcast filter trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_enable_multi_filter(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_enable_multi_filter(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi enable multi filter trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_disable_multi_filter(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_disable_multi_filter(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi disable multi filter trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}
static int l_ncsi_disable_channelTX(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_disable_channelTX(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi disable channelTX trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_enable_channelTX(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);

    ret = ncsi_enable_channelTX(package_id, channel_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi enable channelTX trigger, package_id=%u, channel_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_set_vlan_filter(lua_State *L)
{
    gint32 ret;
    guint8 package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    guchar vlan_filter = luaL_checkinteger(L, 3);
    guchar vlan_state = luaL_checkinteger(L, 4);
    guint32 vlan_id = luaL_checkinteger(L, 5);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 6);

    ret = ncsi_set_vlan_filter(package_id, channel_id, vlan_filter, vlan_state, vlan_id, eth_name);
    debug_log(DLOG_INFO,
        "[ncsi_protocol], ncsi set vlan filter trigger, package_id=%u, channel_id=%u, "\
        "vlan_filter=%u, vlan_state=%u, vlan_id=%u, eth_name=%s, ret=%d.",
        package_id, channel_id, vlan_filter, vlan_state, vlan_id, eth_name, ret);

    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_set_lldp_status(lua_State *L)
{
    gint32 ret;
    gchar *eth_name = (gchar *)luaL_checkstring(L, 1);
    guchar package_id = luaL_checkinteger(L, 2);
    guchar channel_id = luaL_checkinteger(L, 3);
    guchar status = luaL_checkinteger(L, 4);

    ret = update_lldp_over_ncsi_status(eth_name, package_id, channel_id, status);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_enable_vlan_req(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);
    guchar vlan_mode = luaL_checkinteger(L, 4);
    ret = ncsi_enable_vlan_req(package_id, channel_id, eth_name, vlan_mode);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_disable_vlan_req(lua_State *L)
{
    gint32 ret;
    guchar package_id = luaL_checkinteger(L, 1);
    guchar channel_id = luaL_checkinteger(L, 2);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 3);
    ret = ncsi_disable_vlan_req(package_id, channel_id, eth_name);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_get_log(lua_State *L)
{
    guchar package_id = (guchar)luaL_checkinteger(L, 1);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 2);
    gchar *log_dir = (gchar *)luaL_checkstring(L, 3);
    gchar *time = (gchar *)luaL_checkstring(L, 4);
    gint32 ret = get_log_by_ncsi_hw(package_id, eth_name, log_dir, time);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_get_log_new(lua_State *L)
{
    guchar package_id = (guchar)luaL_checkinteger(L, 1);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 2);
    gchar *log_dir = (gchar *)luaL_checkstring(L, 3);
    gchar *time = (gchar *)luaL_checkstring(L, 4);
    gint32 ret = get_log_by_ncsi_hw_new(package_id, eth_name, log_dir, time);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_ncsi_get_blackbox(lua_State *L)
{
    guchar package_id = (guchar)luaL_checkinteger(L, 1);
    gchar *eth_name = (gchar *)luaL_checkstring(L, 2);
    gchar *log_name = (gchar *)luaL_checkstring(L, 3);
    gint32 ret = get_blackbox_by_ncsi_hw(package_id, eth_name, log_name);
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

static int l_get_ncsi_channel_cnt(lua_State *L)
{
    guint32 ret = get_ncsi_channel_cnt();
    lua_pushinteger(L, ret);
    return 1; // 返回1个参数
}

LUAMOD_API int luaopen_ncsi_protocol_intf(lua_State *L)
{
    luaL_checkversion(L);
    luaL_Reg l[] = {
        {"ncsi_common_init", l_ncsi_common_init},
        {"ncsi_paramter_init", l_ncsi_paramter_init},
        {"ncsi_eth_mac_init", l_ncsi_eth_mac_init},
        {"ncsi_receive_packet", l_ncsi_receive_packet},
        {"ncsi_send_cmd", l_ncsi_send_cmd},
        {"ncsi_get_link_status", l_ncsi_get_link_status},
        {"ncsi_clear_initial_state", l_ncsi_clear_initial_state},
        {"ncsi_select_package", l_ncsi_select_package},
        {"ncsi_disable_channel", l_ncsi_disable_channel},
        {"ncsi_enable_channel", l_ncsi_enable_channel},
        {"ncsi_enable_brdcast_filter", l_ncsi_enable_brdcast_filter},
        {"ncsi_disable_brdcast_filter", l_ncsi_disable_brdcast_filter},
        {"ncsi_enable_multi_filter", l_ncsi_enable_multi_filter},
        {"ncsi_disable_multi_filter", l_ncsi_disable_multi_filter},
        {"ncsi_disable_channelTX", l_ncsi_disable_channelTX},
        {"ncsi_enable_channelTX", l_ncsi_enable_channelTX},
        {"ncsi_set_vlan_filter", l_ncsi_set_vlan_filter},
        {"ncsi_enable_vlan_req", l_ncsi_enable_vlan_req},
        {"ncsi_disable_vlan_req", l_ncsi_disable_vlan_req},
        {"ncsi_set_lldp_status", l_ncsi_set_lldp_status},
        {"ncsi_get_log", l_ncsi_get_log},
        {"ncsi_get_log_new", l_ncsi_get_log_new},
        {"ncsi_get_blackbox", l_ncsi_get_blackbox},
        {"get_ncsi_channel_cnt", l_get_ncsi_channel_cnt},
        {NULL, NULL},
    };
    luaL_newlib(L, l);

    return 1;
}
