/* routine to read data from data files */
#include <stdio.h>

#include <string.h>
#include "sect.h"
#include "util.h"

/* MAXMAPLINES is the number of lines of map file that are allocated in
   one pop */
#define MAXMAPLINES 50


/* read the data in a file created by the empire dump command and produce */
/* a list of sectors */
#define DUMPLINESIZE 500
sctlst_t  *read_dump(dumpfile)
char *dumpfile; /* name of the file to be read */
{
  FILE *fp,*fopen();
  char in_line[DUMPLINESIZE]; /* buffer for one line of input data */
  char *ptr; /* pointer into in_line */
  sctlst_t  *p,*the_list;
  int i;
  int junk; /* these next two variables are used to check for */
  char garbage[20]; /* the end of the dump file */
  int shitty; /* a place to stick the avail value */

  if (NULL == (fp = fopen(dumpfile,"r"))) {
    fprintf(stderr,"Cannot open %s for input (expected dumpfile)\n",dumpfile);
    exit(1);
  }
  
  /* verify that it really is a dumpfile */
  fgets(in_line,DUMPLINESIZE,fp); 
  if (0 != strncmp(in_line,"dump",4)) 
    return NULL;

  /* skip the next 3 lines */
  for (i = 0; i < 3; ++i)
    fgets(in_line,DUMPLINESIZE,fp);

  the_list = NULL;

  /* NOTE, this implementation creates the list in reverse order */
  /* i.e. the top of the list is the last entry from the dump file */
  while(fgets(in_line,DUMPLINESIZE,fp)) {

    /* if the line says "# sectors" then it is the last line in the
   	  file and should be ignored */
    sscanf(in_line,"%d %s",&junk,garbage);
    if (0 == strncmp("sectors",garbage,7))
      break;

    /* create a new entry in the sector list and initialize it */
    p = NEW(sctlst_t );
    p->next = the_list;
    the_list = p;
    for (i = 0; i < 6; ++i)
      p->neighbor[i] = NULL;
    p->data = NEW(struct sctstr);

    /* read in the sector data itself */
    sscanf(in_line,"%d %d %c %c %d %d %c %d %d %d %d %d %d %*d %d",
	   &(p->data->sct_x),&(p->data->sct_y),&(p->data->sct_type),
	   &(p->data->sct_newtype),&(p->data->sct_effic),&(p->data->sct_mobil),
	   &(p->data->sct_loyal),&(p->data->sct_min),&(p->data->sct_gmin),
	   &(p->data->sct_fertil),&(p->data->sct_oil),&(p->data->sct_uran),
	   &(p->data->sct_work),
	   &(p->data->sct_terr));

    ptr = in_line;
    for (i = 0; i < 15; ++i)
      ptr = strchr(ptr,' ') + 1;

    /* read in commodities data */
    for (i = 0; i < NUMCOMS; i++) {
      sscanf(ptr,"%d",&(p->data->coms[i]));
      ptr = strchr(ptr,' ') + 1;
    }

    /* read in delivery data */
    p->data->del[CIV] = p->data->del[MIL] = 0; /* can't deliver civ or mil */
    for (i = UNC; i < NUMCOMS; i++) {
      sscanf(ptr,"%c",&(p->data->del[i]));
      ptr = strchr(ptr,' ') + 1;
    }
    
    /* read in cut off data */
    p->data->del[CIV] = p->data->del[MIL] = 0; /* can't deliver civ or mil */
    for (i = UNC; i < NUMCOMS; i++) {
      sscanf(ptr,"%d",&(p->data->cut[i]));
      ptr = strchr(ptr,' ') + 1;
    }
    
    /* read in distibute info */
    sscanf(ptr,"%s %d %d",p->data->dist_path,&(p->data->dist_x),
	   &(p->data->dist_y));
    for (i = 0; i < 3; i++)
      ptr = strchr(ptr,' ') + 1;
    p->data->thrs[CIV] = p->data->thrs[MIL] = 0;
    for (i = UNC; i < NUMCOMS; i++) {
      sscanf(ptr,"%d",&(p->data->thrs[i]));
      ptr = strchr(ptr,' ') + 1;
    }
/* this is a good line to have here, but I'm taking it out because the
   dump files no longer end in a space.  I'm too lazy to make a decent fix 
    if (*ptr != '\n')
      fprintf(stderr,"ERROR: data overflow\n");*/

    /* well, that's all the data */
    /* go on to next row */
  }

  fclose(fp);
  find_neighbors(the_list);
  return the_list;
}




/*
  read a map file and add any sectors sectors not already known to the
  list of sectors in the country
*/  
sctlst_t *
read_map(sctlst_t * country,  char *mapfile)
{
  char** map; /* the entire map, read in at once */
  int i;
  char line[BUFSIZ];
  FILE* fp;
  int maplines;
  int cline; /* current line */
  int col; /* current column in the current line */
  int startx; /* the value of the first X coordinate */
  int firstx;
  int x,y; /* coordinates of the current sector */
  int linelen; /* length of a line in this map file */
  sctlst_t * p;
  sctlst_t * newsec; 
  
  if (NIL(FILE) == (fp = fopen(mapfile, "r"))) {
    fprintf(stderr, "Cannot open %s \n", mapfile);
    return (country);
  }
  
  map = NEWN(char*, MAXMAPLINES);
  for (i = 1; fgets(line, BUFSIZ, fp) != NIL(char); i++) {
    if (i % MAXMAPLINES == 0)
      map = RENEWN(map, char*, i + MAXMAPLINES);
    map[i-1] = strdup(line);
  }
  
  fclose(fp);
  maplines = i - 1;


  if (0 != strncmp(map[0], "map", 3)) {
    fprintf(stderr, "This is not a map file!!!\n");
    return country;
  }

  /* count spaces to find the first x */
  for (firstx = 0; map[1][firstx] == ' '; firstx++)
    ;


  cline = 1;
  startx = 0;
  while (strncmp(map[cline], "         ", firstx - 1) == 0) {
    startx = startx * 10 + (map[cline][firstx] - '0');
    cline += 1;
  }

  /* first location is negative? */
  if (map[cline-1][firstx + 1] - '0' !=
      (map[cline-1][firstx] - '0' + 1) % 10)
    startx = -startx;
  
  maplines = maplines - cline + 1;
  linelen = strlen(map[cline]) - firstx - 1;
  for (; cline < maplines; cline++) {
    y = atoi(map[cline]);
    for (col = firstx, x = startx; col < linelen; x++, col++) {
      if (map[cline][col] != ' ' && map[cline][col] != '.') {
        /* Check country to see if this sector is there already */
        for (p = country; p; p = p->next) {
          if (p->data->sct_x == x && p->data->sct_y == y)
            break;
        }
        if (p == NIL(sctlst_t )) {
          /* add this sector to the map */
          newsec = NEW(sctlst_t );
          newsec->data = NEW(struct sctstr);
          unknown(newsec);
          newsec->data->sct_x = x;
          newsec->data->sct_y = y;
          newsec->data->sct_type = map[cline][col];
          newsec->next = country;
          country = newsec; 
        }
      }
    }
  }

  find_neighbors(country);
  return country;
}

/*
 * Set all the sector fields for p to be unknown (-1)
 */
unknown(sctlst_t * p)
{
  int i;
  
  p->data->sct_x = UNKNOWN;	
  p->data->sct_y = UNKNOWN;	
  p->data->sct_type = UNKNOWN;	
  p->data->sct_newtype = UNKNOWN;
  p->data->sct_effic = UNKNOWN;	
  p->data->sct_mobil = UNKNOWN;	
  p->data->sct_loyal = UNKNOWN;	
  p->data->sct_terr = UNKNOWN;	
  p->data->sct_work = UNKNOWN;	
  p->data->sct_min = UNKNOWN;	
  p->data->sct_gmin = UNKNOWN;	
  p->data->sct_fertil = UNKNOWN;	
  p->data->sct_oil = UNKNOWN;	
  p->data->sct_uran = UNKNOWN;	
  p->data->dist_path[10] = UNKNOWN;
  p->data->dist_x = UNKNOWN;    
  p->data->dist_y = UNKNOWN;    
  for (i = 0; i < NUMCOMS; i++) {
    p->data->coms[i] = UNKNOWN; 
    p->data->del[i] = UNKNOWN;  
    p->data->cut[i] = UNKNOWN;  
    p->data->thrs[i] = UNKNOWN; 
  }
}  


/* set the neighbors field of a sector list to the appropriate sectors */
/* a simple, but inefficient O(N^2) algorithm is used */
find_neighbors(p)
sctlst_t  *p;
{
  sctlst_t  *i,*j;
  int dir; /* direction of adjacency */


  i = p;
  while (i != NULL) {
    j = p;
    while (j != NULL) {
      dir = are_neighbors(i,j);
      if (dir != -1) 
	i->neighbor[dir] = j;
      j = j->next;
    }
    i = i->next;
  }
}


/* return the direction for adjacency (dir 0 == 'y', then go clockwise) */
/* direction is from p to q */
/* return -1 if not adjacent */
are_neighbors(p,q)
sctlst_t  *p,*q;
{
  /* OK first check for 'j' and 'g' directions */
  if (p->data->sct_y == q->data->sct_y) {
    if (p->data->sct_x + 2 == q->data->sct_x)
      return 2;
    else if (p->data->sct_x - 2 == q->data->sct_x)
      return 5;
    else
      return -1;
  }
  else if (p->data->sct_y - 1 == q->data->sct_y) {
    if (p->data->sct_x - 1 == q->data->sct_x)
      return 0;
    else if (p->data->sct_x + 1 == q->data->sct_x)
      return 1;
    else
      return -1;
  }
  else if (p->data->sct_y + 1 == q->data->sct_y) {
    if (p->data->sct_x - 1 == q->data->sct_x)
      return 4;
    else if (p->data->sct_x + 1 == q->data->sct_x)
      return 3;
    else
      return -1;
  }
  else
    return -1;
}

    

      

    
    
       
  
