#include "utils.h"
#include "string.h"
#include "pnal.h"

static void utils_copy_ip_to_struct (
   pnet_cfg_ip_addr_t * destination_struct,
   uint32_t ip)
{
   destination_struct->a = ((ip >> 24) & 0xFF);
   destination_struct->b = ((ip >> 16) & 0xFF);
   destination_struct->c = ((ip >> 8) & 0xFF);
   destination_struct->d = (ip & 0xFF);
}

static int utils_get_netif_namelist (
   const char * arg_str,
   uint16_t max_port,
   utils_netif_namelist_t * p_if_list,
   uint16_t * p_num_ports)
{
   int ret = 0;
   uint16_t i = 0;
   uint16_t j = 0;
   uint16_t if_index = 0;
   uint16_t number_of_given_names = 1;
   uint16_t if_list_size = max_port + 1;
   char c;

   if (max_port == 0)
   {
      printf ("Error: max_port is 0.\n");
      return -1;
   }

   memset (p_if_list, 0, sizeof (*p_if_list));
   c = arg_str[i++];
   while (c != '\0')
   {
      if (c != ',')
      {
         if (if_index < if_list_size)
         {
            p_if_list->netif[if_index].name[j++] = c;
         }
      }
      else
      {
         if (if_index < if_list_size)
         {
            p_if_list->netif[if_index].name[j++] = '\0';
            j = 0;
            if_index++;
         }
         number_of_given_names++;
      }

      c = arg_str[i++];
   }

   if (max_port == 1 && number_of_given_names > 1)
   {
      printf ("Error: Only 1 network interface expected as max_port is 1.\n");
      return -1;
   }
   if (number_of_given_names == 2)
   {
      printf ("Error: It is illegal to give 2 interface names. Use 1, or one "
              "more than the number of physical interfaces.\n");
      return -1;
   }
   if (number_of_given_names > max_port + 1)
   {
      printf (
         "Error: You have given %u interface names, but max is %u as "
         "PNET_MAX_PHYSICAL_PORTS is %u.\n",
         number_of_given_names,
         max_port + 1,
         max_port);
      return -1;
   }

   if (number_of_given_names == 1)
   {
      if (strlen (p_if_list->netif[0].name) == 0)
      {
         printf ("Error: Zero length network interface name.\n");
         return -1;
      }
      else
      {
         p_if_list->netif[1] = p_if_list->netif[0];
         *p_num_ports = 1;
      }
   }
   else
   {
      for (i = 0; i < number_of_given_names; i++)
      {
         if (strlen (p_if_list->netif[i].name) == 0)
         {
            printf ("Error: Zero length network interface name (%d).\n", i);
            return -1;
         }
      }

      *p_num_ports = number_of_given_names - 1;
   }

   return ret;
}

int utils_pnet_cfg_init_netifs (
   const char * netif_list_str,
   utils_netif_namelist_t * if_list,
   uint16_t * number_of_ports,
   pnet_if_cfg_t * if_cfg,
   uint16_t default_mau_type)
{
   int ret = 0;
   int i = 0;
   uint32_t ip;
   uint32_t netmask;
   uint32_t gateway;

   ret = utils_get_netif_namelist (
      netif_list_str,
      PNET_MAX_PHYSICAL_PORTS,
      if_list,
      number_of_ports);
      
   if (ret != 0)
   {
      return ret;
   }
   if_cfg->main_netif_name = if_list->netif[0].name;

   for (i = 1; i <= *number_of_ports; i++)
   {
      if_cfg->physical_ports[i - 1].netif_name = if_list->netif[i].name;
      if_cfg->physical_ports[i - 1].default_mau_type = default_mau_type;
   }

   /* Read IP, netmask, gateway from operating system */
   ip = pnal_get_ip_address (if_cfg->main_netif_name);
   netmask = pnal_get_netmask (if_cfg->main_netif_name);
   gateway = pnal_get_gateway (if_cfg->main_netif_name);

   utils_copy_ip_to_struct (&if_cfg->ip_cfg.ip_addr, ip);
   utils_copy_ip_to_struct (&if_cfg->ip_cfg.ip_gateway, gateway);
   utils_copy_ip_to_struct (&if_cfg->ip_cfg.ip_mask, netmask);

   return ret;
}