#include <xsimple.h>
#include <stdio.h>
#include <stdlib.h>
#include <geolib/cproj.h>
#include "mapview.h"
#include "mapgen.h"

static POINT *pts;
static int npts = 0;
static int penup = TRUE;

static MGMAP *map;
static MGMAPREC *recs, *prevrec;


void drawmapgen(MGMAP *map)
{
   static XPoint p[MAXPOINTS];
   MGMAPREC *rec;
   int np;

   setlinewidth(map->width);

   for (rec = map->recs; rec; rec = rec->next) {
       int i;

       np = 0;
       for (i = 0; i < rec->npts; i++) {
           if (rec->pts[i].lat < minlat || rec->pts[i].lat > maxlat ||
                   rec->pts[i].lon < minlon || rec->pts[i].lon > maxlon) {
               if (np) {
                   if (np > 1) {
                       if (map->fillcolor != -1)
                           fillpoly(p, np, map->fillcolor);
                       poly(p, np, map->color);
                   } else
                       pset(p[0].x, p[0].y, map->color);
               }
               np = 0;
               continue;
           }
           ll2xy(rec->pts[i].lon, rec->pts[i].lat, &(p[np].x), &(p[np].y));
           np++;
       }

       if (np) {
           if (np > 1) {
               if (map->fillcolor != -1)
                   fillpoly(p, np, map->fillcolor);
               poly(p, np, map->color);
           } else
               pset(p[0].x, p[0].y, map->color);
       }
   }
}

static void addrec(MGSEGDICT *sd)
{
   MGMAPREC *rec = (MGMAPREC *)malloc(sizeof(MGMAPREC));
   rec->pts = (POINT *)malloc(npts * sizeof(POINT));
   rec->npts = npts;
   rec->minlat = sd->minlat;
   rec->maxlat = sd->maxlat;
   rec->minlon = sd->minlon;
   rec->maxlon = sd->maxlon;
   rec->next = NULL;

   memcpy(rec->pts, pts, npts * sizeof(POINT));

   if (! recs)
       recs = rec;
   if (prevrec)
       prevrec->next = rec;
   prevrec = rec;
}

static void pendn(double lon, double lat, MGSEGDICT *sd)
{
   if (lat < iminlat || lat > imaxlat || lon < iminlon || lon > imaxlon) {
       if (npts)
           addrec(sd);
       npts = 0;
       return;
   }

   if (penup) {
       if (npts)
           addrec(sd);
       sd->minlat = 1000000.; sd->maxlat = -1000000.;
       sd->minlon = 1000000.; sd->maxlon = -1000000.;
       npts = 0;
       penup = FALSE;
       return;
   }

   if (lat < sd->minlat)
       sd->minlat = lat;
   if (lat > sd->maxlat)
       sd->maxlat = lat;
   if (lon < sd->minlon)
       sd->minlon = lon;
   if (lon > sd->maxlon)
       sd->maxlon = lon;

   pts[npts].lat = lat; pts[npts].lon = lon;

   if (++npts == MAXPOINTS) {
       addrec(sd);
       sd->minlat = 1000000.; sd->maxlat = -1000000.;
       sd->minlon = 1000000.; sd->maxlon = -1000000.;
       npts = 0;
   }
}

MGMAP *loadmapgen(char *fname, unsigned long color, unsigned long fillcolor,
       int width)
{
   FILE *f;
   char s[80];
   MGSEGDICT sd;
   double lastlon = 0.;
   double lon, lat;

   if (! (f = fopen(fname, "r"))) {
       perror("fopen");
       exit(1);
   }

   pts = (POINT *)malloc(MAXPOINTS * sizeof(POINT));
   npts = 0;
   recs = prevrec = NULL;

   while (fgets(s, 80, f)) {
       if (*s == '*')
           continue;
       if (*s == '#') {
           penup = TRUE;
           pendn(minlon, minlat, &sd);
           continue;
       }
       sscanf(s, "%lf %lf", &lon, &lat);
       if (fabs(lastlon - lon) > 180.)
           penup = TRUE;
       pendn(lon, lat, &sd);
       lastlon = lon;
   }
   if (npts)
       addrec(&sd);

   fclose(f);
   free(pts);

   map = (MGMAP *)malloc(sizeof(MGMAP));
   map->type = MAPGEN;
   map->color = color;
   map->fillcolor = fillcolor;
   map->width = width;
   map->recs = recs;
   map->next = NULL;
   return map;
}