/**
 * @file        lwip.c
 *
 * @brief       LwIP program body
 *
 * @version     V1.0.0
 *
 * @date        2025-05-08
 *
 * @attention
 *
 *  Copyright (C) 2025 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes ***************************************************************/
#include "lwip.h"

/* Private includes *******************************************************/
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#if defined ( __CC_ARM )
#include "lwip/sio.h"
#endif /* MDK ARM Compiler */
#include "ethernetif.h"
#include "netif/etharp.h"
#include "log.h"

#include <stdio.h>
#include <string.h>

/* Private macro **********************************************************/

/* Configurate local ETH information */
#define ETH_IP_ADDR         "192.168.1.22"
#define ETH_NET_MASK        "255.255.255.0"
#define ETH_GATEWAY         "192.168.1.1"

/* Private typedef ********************************************************/

/* Private variables ******************************************************/
static const char* tag = "lwip";
uint32_t ethLinkTimer;

struct netif userNetif;
ip4_addr_t ipaddr;
ip4_addr_t netmask;
ip4_addr_t gw;

/* Private function prototypes ********************************************/
static void LWIP_LinkStatusUpdated(struct netif *netif);
static void LWIP_EthLinkPeriodicHandle(struct netif *netif);

/* External variables *****************************************************/

/* External functions *****************************************************/

/**
 * @brief   LwIP program
 *
 * @param   None
 *
 * @retval  None
 */
void LWIP_Init(void)
{
    int ipAddrTemp[4];
    int netMaskTemp[4];
    int gatewayTemp[4];

    /* Initilialize the LwIP stack */
    lwip_init();

#if LWIP_DHCP
  ip_addr_set_zero_ip4(&ipaddr);
  ip_addr_set_zero_ip4(&netmask);
  ip_addr_set_zero_ip4(&gw);
#else
    sscanf(ETH_IP_ADDR, "%d.%d.%d.%d", &ipAddrTemp[0], &ipAddrTemp[1], &ipAddrTemp[2], &ipAddrTemp[3]);
    sscanf(ETH_NET_MASK, "%d.%d.%d.%d", &netMaskTemp[0], &netMaskTemp[1], &netMaskTemp[2], &netMaskTemp[3]);
    sscanf(ETH_GATEWAY, "%d.%d.%d.%d", &gatewayTemp[0], &gatewayTemp[1], &gatewayTemp[2], &gatewayTemp[3]);

    IP4_ADDR(&ipaddr, ipAddrTemp[0], ipAddrTemp[1], ipAddrTemp[2], ipAddrTemp[3]);
    IP4_ADDR(&netmask, netMaskTemp[0], netMaskTemp[1], netMaskTemp[2], netMaskTemp[3]);
    IP4_ADDR(&gw, gatewayTemp[0], gatewayTemp[1], gatewayTemp[2], gatewayTemp[3]);

    LOGI(tag,"ETH_IP       : %d.%d.%d.%d\r\n", ipAddrTemp[0], ipAddrTemp[1], ipAddrTemp[2], ipAddrTemp[3]);
    LOGI(tag,"ETH_Net_Mask : %d.%d.%d.%d\r\n", netMaskTemp[0], netMaskTemp[1], netMaskTemp[2], netMaskTemp[3]);
    LOGI(tag,"ETH_Gateway  : %d.%d.%d.%d\r\n", gatewayTemp[0], gatewayTemp[1], gatewayTemp[2], gatewayTemp[3]);
#endif /* LWIP_DHCP */

    /* Add the network interface */
    netif_add(&userNetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);

    /* Registers the default network interface */
    netif_set_default(&userNetif);

    netif_set_up(&userNetif);

    /* Set the link callback function, this function is called on change of link status*/
    netif_set_link_callback(&userNetif, LWIP_LinkStatusUpdated);
}

/**
 * @brief   Read a received packet and send it to the LwIP stack
 *
 * @param   None
 *
 * @retval  None
 */
void LWIP_Process(void)
{
    /* Read a received packet from the Ethernet buffers and send it 
       to the lwIP for handling */
    ethernetif_input(&userNetif);

    /* Handle timeouts */
    sys_check_timeouts();
    
    LWIP_EthLinkPeriodicHandle(&userNetif);
}

/**
 * @brief   Ethernet Link periodic check
 *
 * @param   netif
 *
 * @retval  None
 */
static void LWIP_EthLinkPeriodicHandle(struct netif *netif)
{
    /* Ethernet Link every 100ms */
    if (DAL_GetTick() - ethLinkTimer >= 100)
    {
        ethLinkTimer = DAL_GetTick();
        ethernetif_checkEthLinkState(netif);
    }
}

/**
 * @brief   Notify the User about the network interface config status
 *
 * @param   netif: the network interface
 *
 * @retval  None
 */
static void LWIP_LinkStatusUpdated(struct netif *netif)
{
    if (netif_is_up(netif))
    {
        
    }
    /* netif is down */
    else
    {
        
    }
}
