/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <vppinfra/graph.h>

/* Set link distance, creating link if not found. */
u32
graph_set_link (graph_t * g, u32 src, u32 dst, u32 distance)
{
  graph_node_t *src_node, *dst_node;
  graph_link_t *l;
  u32 old_distance;

  /* The following validate will not work if src or dst are on the
     pool free list. */
  if (src < vec_len (g->nodes))
    ASSERT (!pool_is_free_index (g->nodes, src));
  if (dst < vec_len (g->nodes))
    ASSERT (!pool_is_free_index (g->nodes, dst));

  /* Make new (empty) nodes to make src and dst valid. */
  pool_validate_index (g->nodes, clib_max (src, dst));

  src_node = pool_elt_at_index (g->nodes, src);
  dst_node = pool_elt_at_index (g->nodes, dst);

  l = graph_dir_get_link_to_node (&src_node->next, dst);
  if (l)
    {
      old_distance = l->distance;
      l->distance = distance;

      l = graph_dir_get_link_to_node (&dst_node->prev, src);
      l->distance = distance;
    }
  else
    {
      uword li_next, li_prev;

      old_distance = ~0;

      li_next = graph_dir_add_link (&src_node->next, dst, distance);
      li_prev = graph_dir_add_link (&dst_node->prev, src, distance);

      l = vec_elt_at_index (src_node->next.links, li_next);
      l->link_to_self_index = li_prev;

      l = vec_elt_at_index (dst_node->prev.links, li_prev);
      l->link_to_self_index = li_next;
    }

  return old_distance;
}

void
graph_del_link (graph_t * g, u32 src, u32 dst)
{
  graph_node_t *src_node, *dst_node;

  src_node = pool_elt_at_index (g->nodes, src);
  dst_node = pool_elt_at_index (g->nodes, dst);

  graph_dir_del_link (&src_node->next, dst);
  graph_dir_del_link (&dst_node->next, src);
}

/* Delete source node and all links from other nodes from/to source. */
uword
graph_del_node (graph_t * g, u32 src)
{
  graph_node_t *src_node, *n;
  uword index;
  graph_link_t *l;

  src_node = pool_elt_at_index (g->nodes, src);

  vec_foreach (l, src_node->next.links)
  {
    n = pool_elt_at_index (g->nodes, l->node_index);
    graph_dir_del_link (&n->prev, src);
  }

  vec_foreach (l, src_node->prev.links)
  {
    n = pool_elt_at_index (g->nodes, l->node_index);
    graph_dir_del_link (&n->next, src);
  }

  graph_dir_free (&src_node->next);
  graph_dir_free (&src_node->prev);

  index = src_node - g->nodes;
  pool_put (g->nodes, src_node);
  memset (src_node, ~0, sizeof (src_node[0]));

  return index;
}

uword
unformat_graph (unformat_input_t * input, va_list * args)
{
  graph_t *g = va_arg (*args, graph_t *);
  typedef struct
  {
    u32 src, dst, distance;
  } T;
  T *links = 0, *l;
  uword result;

  while (1)
    {
      vec_add2 (links, l, 1);
      if (!unformat (input, "%d%d%d", &l->src, &l->dst, &l->distance))
	break;
    }
  _vec_len (links) -= 1;
  result = vec_len (links) > 0;
  vec_foreach (l, links)
  {
    graph_set_link (g, l->src, l->dst, l->distance);
    graph_set_link (g, l->dst, l->src, l->distance);
  }

  vec_free (links);
  return result;
}

u8 *
format_graph_node (u8 * s, va_list * args)
{
  graph_t *g = va_arg (*args, graph_t *);
  u32 node_index = va_arg (*args, u32);

  if (g->format_node)
    s = format (s, "%U", g->format_node, g, node_index);
  else
    s = format (s, "%d", node_index);

  return s;
}

u8 *
format_graph (u8 * s, va_list * args)
{
  graph_t *g = va_arg (*args, graph_t *);
  graph_node_t *n;
  graph_link_t *l;
  uword indent = format_get_indent (s);

  s = format (s, "graph %d nodes", pool_elts (g->nodes));
  /* *INDENT-OFF* */
  pool_foreach (n, g->nodes, ({
    s = format (s, "\n%U", format_white_space, indent + 2);
    s = format (s, "%U -> ", format_graph_node, g, n - g->nodes);
    vec_foreach (l, n->next.links)
      s = format (s, "%U (%d), ",
		  format_graph_node, g, l->node_index,
		  l->distance);
  }));
  /* *INDENT-ON* */

  return s;
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
