/* Copyright (c) 2000  Kevin Sullivan <nite@gis.net>
 *
 * Please refer to the COPYRIGHT file for more information.
 */

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <ncurses.h>

#include "defines.h"
#include "cmds.h"
#include "scmds.h"
#include "handlers.h"
#include "nap.h"

#ifdef MEMWATCH
  #include "memwatch.h"
#endif

handler_t *hndhead;


unsigned char *dohandler(handler_t *al, char **tok, int cnt)
{
  char *ret, echr;
  char **atok, p[16], pt[2048], tb[2048], *t;
  int i, j, acnt, n, l, c;
  
  t = strdup(al->args);
  
  for (i=0;al->args[i]&&al->args[i] == ' ';i++);
  
  if (al->args[i] == '{')
  {
    for (i=0,c=0;t[i];i++)
    {
      if (c < 0)
        c = 0;
      if (t[i] == '{' && !c)
      {
        t[i] = ' ';
        c++;
      }
      else if (t[i] == '{')
        c++;
      else if (t[i] == '}' && c == 1)
      {
        t[i] = ' ';
        c--;
      }
      else if (t[i] == '}')
        c--;
    }
  }
  
  if (t[strlen(t)-1] == '|' || t[strlen(t)-1] == '\n')
    t[strlen(t)-1] = 0;
  
  memset(pt, 0, sizeof(pt));
  strcpy(pt, t);
  free(t);
  
  for (i=0;pt[i];i++)
  {
    if (pt[i] == '$' || pt[i] == '?')
    {
      for (j=i,echr=0;;j++)
      {
        if (!pt[j] || pt[j] == ',' || pt[j] == ' ' || pt[j] == '=' || pt[j] == '!' || pt[j] == '>' || pt[j] == '<')
        {
          echr = pt[j];
          break;
        }
      }
      if (i > 0 && (pt[i-1] == '(' || pt[i-1] == ')' || pt[i-1] == ',' || pt[i-1] == '=' || pt[i-1] == '!' || pt[i-1] == '<' || pt[i-1] == '>' || pt[i-1] == ' '))
      {
        if (pt[i-1] != ' ')
        {
          memset(tb, 0, sizeof(tb));
          strcpy(tb, pt+i);
          strcpy(pt+i+1, tb);
          pt[i] = ' ';
        }
        else
          j--;
        if (echr && echr != ' ')
        {
          memset(tb, 0, sizeof(tb));
          strcpy(tb, pt+j+1);
          strcpy(pt+j+2, tb);
          pt[j+1] = ' ';
        }
      }
    }
  }
  
  t = strdup(pt);
  
  atok = form_tokso(t, &acnt);
  free(t);
  
  for (i=0,j=0;i<acnt;i++)
    if (*atok[i] == '$' && atok[i][1])
      if (atoi(atok[i]+1) > j)
        j = atoi(atok[i]+1);

  if ((cnt-1) < j)
    return(NULL);
  
  for (i=0;atok[i];i++)
  {
    if (*atok[i] == '?' && isdigit(atok[i][1]))
    {
      if (atoi(atok[i]+1) <= (cnt-1))
        *atok[i] = '$';
      else
      {
        for (j=1;;j++)
        {
          if (!isdigit(atok[i][j]) && atok[i][j] != '-')
          {
            memset(tb, 0, sizeof(tb));
            strcpy(tb, atok[i]+j);
            strcpy(atok[i], tb);
            break;
          }
        }
      }
    }
  }
  
  for (i=0,l=0;atok[i];i++)
  {
    if (*atok[i] == '$' && isdigit(atok[i][1]) && !strchr(atok[i], '-'))
    {
      n = atoi(atok[i]+1);
      memset(tb, 0, sizeof(tb));
      for (j=1;atok[i][j];j++)
        if (!isdigit(atok[i][j]))
          break;
      strcpy(tb, atok[i]+j);
      atok[i] = (char *)realloc(atok[i], strlen(tok[n])+strlen(tb)+1);
      strcpy(atok[i], tok[n]);
      strcat(atok[i], tb);
    }
    else if (*atok[i] == '$' && isdigit(atok[i][1]))
    {
      memset(p, 0, sizeof(p));
      for (j=1;;j++)
      {
        if (!isdigit(atok[i][j]) && atok[i][j] != '-')
        {
          memset(tb, 0, sizeof(tb));
          strcpy(tb, atok[i]+j);
          strcpy(atok[i], tb);
          break;
        }
        if (atok[i][j] != '-')
          p[j-1] = atok[i][j];
      }
      n = atoi(p);
      memset(pt, 0, sizeof(pt));
      for (j=n;tok[j];j++)
      {
        strcat(pt, tok[j]);
        strcat(pt, " ");
      }
      pt[strlen(pt)-1] = 0;
      atok[i] = (char *)realloc(atok[i], strlen(pt)+strlen(tb)+1);
      strcpy(atok[i], pt);
      strcat(atok[i], tb);
    }
    else if (*atok[i] == '$' && !strcasecmp(atok[i]+1, "num"))
    {
      free(atok[i]);
      atok[i] = NULL;
      msprintf(&atok[i], "%i", cnt-1);
    }
    else if (*atok[i] == '$' && !strcasecmp(atok[i]+1, "str"))
    {
      free(atok[i]);
      atok[i] = (char *)malloc(4096);
      memset(atok[i], 0, 4096);
      for (j=0;tok[j];j++)
      {
        if (*tok[j])
        {
          strcat(atok[i], tok[j]);
          strcat(atok[i], " ");
        }
      }
      atok[i][strlen(atok[i])-1] = 0;
      atok[i] = (char *)realloc(atok[i], strlen(atok[i])+1);
    }
    l+=strlen(atok[i])+1;
  }

  ret = (char *)malloc(4096);
  memset(ret, 0, 4096);
  
  for (i=0;atok[i];i++)
  {
    if (*atok[i])
    {
      strcat(ret, atok[i]);
      strcat(ret, " ");
    }
    free(atok[i]);
  }
  
  free(atok);
  
  ret[strlen(ret)-1] = 0;
  ret = (char *)realloc(ret, strlen(ret)+1);
  
  return((unsigned char *)ret);
}

int loadhandlers(char *fn)
{
  FILE *f;
  handler_t *cur, *cur1=NULL;
  char buf[4096], tb[4096];
  int i, c, j;
  
  f = fopen(fn, "r");
  if (!f)
    return(-1);
  
  for (cur=hndhead;cur;cur=cur->next)
    cur1 = cur;
  
  while (1)
  {
    if (fgets(buf, sizeof(buf), f) == NULL)
      break;
    if (*buf == '#')
      continue;
    if (buf[strlen(buf)-1] == '\n')
      buf[strlen(buf)-1] = 0;
    for (i=0,c=0;buf[i];i++)
    {
      if (buf[i] == ' ')
      {
        c = 1;
        break;
      }
    }
    
    if (!c)
    {
      buf[strlen(buf)] = ' ';
      fgets(buf+strlen(buf), sizeof(buf)-strlen(buf), f);
      if (buf[strlen(buf)-1] == '\n')
        buf[strlen(buf)-1] = 0;
    }
    
    buf[strlen(buf)] = '\n';
    
    for (c=0,i=0;;i++)
    {
      if (c < 0)
      {
        c = 0;
        break;
      }
      if (!buf[i] && c)
      {
        while (1)
        {
          memset(tb, 0, sizeof(tb));
          if (fgets(tb, sizeof(tb), f) == NULL)
	    break;
          for (j=0;tb[j]==' ';j++);
          if (tb[j] != '#')
          {
            strcpy(buf+i+1, tb);
            buf[i] = ' ';
            break;
          }
        }
      }
      else if (!buf[i])
        break;
      if (buf[i] == '{')
        c++;
      else if (buf[i] == '}')
        c--;
    }
    
    for (i=0;buf[i];i++)
    {
      if (buf[i] == '\n')
      {
        for (j=i+1;buf[j]==' '&&buf[j]!='{';j++);
        if (buf[j] == '{')
        {
          buf[i] = ' ';
          strncpy(buf+i+1, buf+j, strlen(buf+j));
          buf[strlen(buf)-(j-i)+1] = 0;
        }
      }
    }
    if (*buf == ' ')
      continue;
    for (i=strlen(buf)-1;buf[i] == ' '&&i>=0;i--);
    while (buf[i] == '\n')
    {
      buf[i] = 0;
      i--;
    }
    cur = (handler_t *)malloc(sizeof(handler_t));
    for (i=0;buf[i]!=' ';i++);
    cur->args = strdup(buf+i+1);
    if (buf[0] == '0' && buf[1] == 'x')
      cur->op = strtol(buf, (char **)NULL, 16);
    else
      cur->op = atoi(buf);
    cur->next = NULL;
    if (!cur1)
      hndhead = cur;
    else
      cur1->next = cur;
    cur1 = cur;
  } /* while (1) */
  
  fclose(f);
  
  return(1);
}

int savehandlers(char *fn)
{
  FILE *f;
  handler_t *cur;
  
  f = fopen(fn, "w");
  if (!f)
    return(-1);
  
  for (cur=hndhead;cur;cur=cur->next)
    fprintf(f, "%i %s\n", cur->op, cur->args);
  
  fclose(f);
  
  return(1);
}

