/* pcdl.c - Function dealing with the Phone Category Language
 *
 * This file is part of TUA.
 *
 *   Copyright (C) 1991,92,93  Lele Gaifax (lele@nautilus.sublink.org)
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the license, or (at
 *   your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "tua.h"
#include "pcdl.h"

static pcdl_slot_list * slot_list = 0;
static pcdl_name_list * name_list = 0;

void
DEFUN_VOID(pcdl_reset_names)
{
  name_list = 0;
}

void
DEFUN_VOID(pcdl_reset_slots)
{
  slot_list = 0;
}

pcdl_slot_list *
DEFUN_VOID (pcdl_slots)
{
  return slot_list;
}

pcdl_name_list *
DEFUN_VOID (pcdl_names)
{
  return name_list;
}

pcdl_slot *
DEFUN(pcdl_insert_slot, (slot),
      pcdl_slot * slot)
{
  if (slot_list)
    {
      pcdl_slot_list * node = slot_list;

      while (node->slot->from < slot->from && node->next)
	node = node->next;

      if (node->slot->from != slot->from)
	{
	  pcdl_slot_list * new = (pcdl_slot_list *) xmalloc (sizeof (pcdl_slot_list));

	  new->slot = slot;
	  
	  if (node->slot->from < slot->from)
	    {
	      new->next = node->next;
	      node->next = new;
	    }
	  else
	    {
	      pcdl_slot_list swap;

	      swap.slot = node->slot;
	      swap.next = node->next;
	      node->slot = new->slot;
	      node->next = new;
	      new->slot = swap.slot;
	      new->next = swap.next;
	    }
	}
    }
  else
    {
      slot_list = (pcdl_slot_list *) xmalloc (sizeof (struct pcdl_slot_list));

      slot_list->slot = slot;
      slot_list->next = 0;
    }
  
  return slot;
}
  
pcdl_slot *
DEFUN_VOID (pcdl_create_new_slot)
{
  pcdl_slot * new = (pcdl_slot *) xmalloc (sizeof (pcdl_slot));

  return new;
}

pcdl_name *
DEFUN(pcdl_insert_name, (name),
      pcdl_name * name)
{
  if (name_list)
    {
      pcdl_name_list * node = name_list;

      while (node->name->cost < name->cost && node->next)
	node = node->next;

      if (node->name->cost != name->cost)
	{
	  pcdl_name_list * new = (pcdl_name_list *) xmalloc (sizeof (pcdl_name_list));

	  new->name = name;
	  
	  if (node->name->cost < name->cost)
	    {
	      new->next = node->next;
	      node->next = new;
	    }
	  else
	    {
	      pcdl_name_list swap;

	      swap.name = node->name;
	      swap.next = node->next;
	      node->name = new->name;
	      node->next = new;
	      new->name = swap.name;
	      new->next = swap.next;
	    }
	}
    }
  else
    {
      name_list = (pcdl_name_list *) xmalloc (sizeof (struct pcdl_name_list));

      name_list->name = name;
      name_list->next = 0;
    }
  
  return name;
}
  
pcdl_name *
DEFUN_VOID (pcdl_create_new_name)
{
  pcdl_name * new = (pcdl_name *) xmalloc (sizeof (pcdl_name));

  return new;
}

CONST char * default_country_name = 0;

CONST char *
DEFUN (pcd_rate_name, (rate),
       int rate)
{
  pcdl_name_list * nl = current_country.names;
  
  for (nl = current_country.names; nl && nl->name->cost != rate; nl = nl->next)
    ;

  return nl->name->name;
}
  
static pcdl_name_list * symbol_list = 0;

int
DEFUN (pcdl_lookup_rate_symbol, (symbol, ins_flag),
       CONST char * symbol AND int ins_flag)
{
  if (symbol_list)
    {
      pcdl_name_list * new, * sl = symbol_list;
      
      while (1)
	{
	  if (strcmp (symbol, sl->name->name) == 0)
	    return sl->name->cost;

	  if (sl->next == 0)
	    break;
	  else
	    sl = sl->next;
	}

      if (ins_flag)
	{
	  pcdl_name * n = pcdl_create_new_name ();

	  n->name = savestring (symbol);
	  n->cost = sl->name->cost+1;
	  
	  new = (pcdl_name_list *) xmalloc (sizeof (struct pcdl_name_list));
	  new->name = n;
	  new->next = 0;
	  sl->next = new;
	  return n->cost;
	}
      else
	{
	  LOG("Rate symbol %s not yet defined!\n", symbol);
	  exit(1);
	}
    }
  else
    {
      pcdl_name * n = pcdl_create_new_name();
      
      symbol_list = (pcdl_name_list *) xmalloc (sizeof (struct pcdl_name_list));
      n->name = savestring (symbol);
      n->cost = 1;
      symbol_list->name = n;
      symbol_list->next = 0;
      return 1;
    }
}
  
void
DEFUN_VOID (pcdl_destroy_symbol_list)
{
  while (symbol_list)
    {
      pcdl_name * n = symbol_list->name;
      pcdl_name_list * next = symbol_list->next;
      
      xfree (n->name);
      xfree (n);
      
      xfree (symbol_list);
      symbol_list = next;
    }
}
      
	  
	  
    
