#include <exec/types.h>
#include <exec/libraries.h>
#include <dos/dos.h>

#include <cmshared/jblist.h>
#include <cmshared/config.h>

#include <stdio.h>

#include <clib/exec_protos.h>

/* TrapList */

#include <pd/nl.h>

struct Library *NodelistBase;
NodeList nodelist;

/* Gotcha */

#include <clib/gotchalib_protos.h>
#include <libraries/gotchalib.h>

struct Library *GotchaLibBase;
struct gl_context *cont;

void Copy4D(struct Node4D *node1,struct Node4D *node2);
int Compare4D(struct Node4D *node1,struct Node4D *node2);

BOOL nlStart(UBYTE *errbuf)
{
   if(cfg_NodeListType == NODELIST_TRAPLIST)
   {
      if(!(NodelistBase = (struct Library *)OpenLibrary(TRAPLIST_NAME, TRAPLIST_VER)))
      {
         sprintf(errbuf,"Unable to open traplist.library V5 or higher!");
         return(FALSE);
      }

      if(!(nodelist=NLOpen(cfg_NodeList, 0)))
      {
         sprintf(errbuf,"Error opening TrapList nodelist in directory \"%s\"",cfg_NodeList);
         CloseLibrary(NodelistBase);
         return(FALSE);
      }
   }

   if(cfg_NodeListType == NODELIST_GOTCHA)
   {
      if(!(GotchaLibBase = OpenLibrary("gotcha.library",1)))
      {
         sprintf(errbuf,"Unable to open gotcha.library V1 or higher!");
         return(FALSE);
      }

		if(!(cont = GL_OpenNL(cfg_NodeList)))
      {
         sprintf(errbuf,"Error opening Gotcha nodelist in directory \"%s\"",cfg_NodeList);
         CloseLibrary(GotchaLibBase);
         return(FALSE);
      }
   }

   return(TRUE);
}

void nlEnd(void)
{
   if(cfg_NodeListType == NODELIST_TRAPLIST)
   {
      NLClose(nodelist);
      CloseLibrary(NodelistBase);
   }

   if(cfg_NodeListType == NODELIST_GOTCHA)
   {
      GL_CloseNL(cont);
      CloseLibrary(GotchaLibBase);
   }
}

nlCheckNode(struct Node4D *node)
{
   if(cfg_NodeListType == NODELIST_TRAPLIST)
   {
      NodeDesc *nodedesc;
      Addr findaddr;

      findaddr.Zone=node->Zone;
      findaddr.Net=node->Net;
      findaddr.Node=node->Node;
      findaddr.Point=0;

      if(nodedesc = NLFind(nodelist,&findaddr, 0))
      {
         NLFreeNode(nodedesc);
         return(TRUE);
      }
   }

   if(cfg_NodeListType == NODELIST_GOTCHA)
   {
      UBYTE buf[50];
      struct gl_address add;
      struct gl_nodeinfo ninfo;

      sprintf(buf,"%lu:%lu/%lu",
         node->Zone,
         node->Net,
         node->Node);

      GL_XtractInfos(&add,buf);

		if(GL_FindNode(&add,cont,&ninfo,NULL))
         return(TRUE);
   }

   return(FALSE);
}

/* Caches last node for nlGetRegion and nlGetHub */

struct Node4D nl_getxxxcache_Node4D={0,0,0,0};
UWORD nl_getxxxcache_Region=0,nl_getxxxcache_Hub=0;

int nlGetRegion(struct Node4D *node)
{
   if(Compare4D(&nl_getxxxcache_Node4D,node)==0)
      return(nl_getxxxcache_Region);

   Copy4D(&nl_getxxxcache_Node4D,node);
   nl_getxxxcache_Region = -1;
   nl_getxxxcache_Hub = -1;

   if(cfg_NodeListType == NODELIST_TRAPLIST)
   {
      NodeDesc *nodedesc;
      Addr findaddr;

      findaddr.Zone=node->Zone;
      findaddr.Net=node->Net;
      findaddr.Node=node->Node;
      findaddr.Point=0;

      if(nodedesc = NLFind(nodelist,&findaddr, 0))
      {
         nl_getxxxcache_Region=nodedesc->Region;
         nl_getxxxcache_Hub=nodedesc->Hub;
         NLFreeNode(nodedesc);
      }
   }

   if(cfg_NodeListType == NODELIST_GOTCHA)
   {
      UBYTE buf[50];
      struct gl_address add;
      struct gl_nodeinfo ninfo;

      sprintf(buf,"%lu:%lu/%lu",
         node->Zone,
         node->Net,
         node->Node);

      GL_XtractInfos(&add,buf);

		if(GL_FindNode(&add,cont,&ninfo,NULL))
      {
         nl_getxxxcache_Region=ninfo.region;
         nl_getxxxcache_Hub=ninfo.hub;
      }
   }

   return(nl_getxxxcache_Region);
}

int nlGetHub(struct Node4D *node)
{
   if(Compare4D(&nl_getxxxcache_Node4D,node)==0)
      return(nl_getxxxcache_Hub);

   Copy4D(&nl_getxxxcache_Node4D,node);
   nl_getxxxcache_Region = -1;
   nl_getxxxcache_Hub = -1;

   if(cfg_NodeListType == NODELIST_TRAPLIST)
   {
      NodeDesc *nodedesc;
      Addr findaddr;

      findaddr.Zone=node->Zone;
      findaddr.Net=node->Net;
      findaddr.Node=node->Node;
      findaddr.Point=0;

      if(nodedesc = NLFind(nodelist,&findaddr, 0))
      {
         nl_getxxxcache_Region=nodedesc->Region;
         nl_getxxxcache_Hub=nodedesc->Hub;
         NLFreeNode(nodedesc);
      }
   }

   if(cfg_NodeListType == NODELIST_GOTCHA)
   {
      UBYTE buf[50];
      struct gl_address add;
      struct gl_nodeinfo ninfo;

      sprintf(buf,"%lu:%lu/%lu",
         node->Zone,
         node->Net,
         node->Node);

      GL_XtractInfos(&add,buf);

		if(GL_FindNode(&add,cont,&ninfo,NULL))
      {
         nl_getxxxcache_Region=ninfo.region;
         nl_getxxxcache_Hub=ninfo.hub;
      }
   }

   return(nl_getxxxcache_Hub);
}

