/* drawing routines for PlotMap */

#include "PlotMap.h"

/********** externals **********/

extern struct mapinfo map[];
extern struct point *loadmap_buffer;
extern struct Screen *screen;
extern struct RastPort *rp;
extern struct config config;

extern BPTR get_map_fhd(UWORD);

/********** Variablen, Daten **********/

UWORD old_maptype = ~0;             /* ~0 indicates no map */
WORD detail_level;

double act_vfactor, m_vfactor;
UWORD centerx, centery, half_scr_width;
WORD box_x1 = -180*60, box_x2 = 180*60;
WORD box_y1 = 90*60, box_y2 = -90*60;

/********** Routinen **********/

void get_detail_level(void)
{
   WORD bw, dlm;

   if (config.detail_level <= DL_LOW)
      detail_level = config.detail_level;
   else
   {                                   /* auto detail level */
      bw = box_x2 - box_x1;
      dlm = DL_LOW+1;

      if (bw < 150*60)
         dlm = DL_LOW;
      if (bw < 70*60)
         dlm = DL_MEDIUMLOW;
      if (bw < 35*60)
         dlm = DL_MEDIUM;
      if (bw < 15*60)
         dlm = DL_MEDIUMHIGH;

      detail_level = dlm - (DL_AUTO_LOW - config.detail_level);

      if (detail_level > DL_LOW)
         detail_level = DL_LOW;
      if (detail_level < DL_HIGH)
         detail_level = DL_HIGH;
   }
}



void draw_fullmap(UWORD type)
/* type can be MAP_FLAT or MAP_MERCATOR */
{
   WORD x, y, old_x = -1, old_y = -1, width, height, vfac2;
   LONG t2;
   UWORD anz, map_zhl, seg_zhl;
   ULONG first, last, pt_zhl;
   BOOL new_seg, error;
   BPTR fhd = NULL;
   double t;
   struct arc *seg;
   struct point *pt;
   struct IntuiMessage *msg;
   BOOL abort = FALSE;

   RMBTRAP_ON;
   IDCMP(IDCMP_MOUSEBUTTONS);
   MOUSE_WAIT;
   TITLE_MSG("Drawing map, press RMB to abort");

   box_x1 = -180*60;
   box_x2 = 180*60;
   box_y1 = 90*60;
   box_y2 = -90*60;

   get_detail_level();
   width = screen->Width;
   height = screen->Height;
   vfac2 = (WORD)(180.0*60.0 * act_vfactor);

   old_maptype = type | MAP_PLANE;
   OnMenu(main_wd, FULLMENUNUM(3,1,NOSUB));     /* Box */
   OffMenu(main_wd, FULLMENUNUM(3,1,3));        /* Box zoom */
   OffMenu(main_wd, FULLMENUNUM(3,1,4));
   OffMenu(main_wd, FULLMENUNUM(3,2,3));        /* Sphere zoom */
   OffMenu(main_wd, FULLMENUNUM(3,2,4));
   OnMenu(main_wd, FULLMENUNUM(3,4,NOSUB));     /* Redraw */

   if (config.cls_before_draw)
      SetRast(rp, config.bg_color);                   /* clear screen */

   for (map_zhl = 0; map_zhl < NUM_MAPS; map_zhl++)   /* do each map type */
   {
      if (config.plotmap[map_zhl] && !abort)    /* if not requested, skip */
      {
         error = FALSE;
         SetAPen(rp, config.mapcolor[map_zhl]); /* initialize color */
         seg = map[map_zhl].seg;

         if (config.loadmap[map_zhl])           /* map loaded? */
            pt = map[map_zhl].pt;
         else
         {
            pt = loadmap_buffer;                /* no, open map */
            if (!(fhd = get_map_fhd(map_zhl)))
            {
               TITLE_ERROR("Can`t open map file!");
               error = TRUE;
            }
         } /* if (config.loadmap[]) */
                                                /* do each segment */
         for (seg_zhl = 0; seg_zhl < map[map_zhl].nsegs && !error; seg_zhl++)
         {
            /* check for user abort */
            if (msg = (struct IntuiMessage *)GetMsg(main_wd->UserPort))
            {
               if ((msg->Class == IDCMP_MOUSEBUTTONS) && (msg->Code == MENUDOWN))
               {
                  ReplyMsg((struct Message *)msg);    /* user aborted */
                  DisplayBeep(NULL);
                  abort = TRUE;
                  break;
               }
               ReplyMsg((struct Message *)msg);
            } /* if (GetMsg()) */

            if (config.loadmap[map_zhl])        /* map loaded? */
            {
               first = seg[seg_zhl].first;      /* somewhere from the */
               last = seg[seg_zhl].last;        /* whole map */
            }
            else
            {                    /* load whole next segment into buffer */
               anz = seg[seg_zhl].last - seg[seg_zhl].first + 1;
               if (Read(fhd, loadmap_buffer, anz*sizeof(struct point)) !=
                     anz * sizeof(struct point))
               {
                  TITLE_ERROR("Can`t read map file!");
                  error = TRUE;
                  break;                        /* exit seg_zhl-loop */
               }

               first = 0;              /* from beginning of load-buffer */
               last = anz-1;
            } /* if (config.loadmap[]) */

            new_seg = TRUE;            /* we start a new segment */

            for (pt_zhl = first; pt_zhl <= last; pt_zhl++)
            {
               if (pt[pt_zhl].code >= detail_level)
               {                                /* filter by detail level */
                  if (type == MAP_FLAT)
                  {
                     t2 = pt[pt_zhl].lat * height;    /* y = lattitude */
                     if (t2 < 0)                /* round to nearest pixel */
                        t2 -= 180*30;
                     else
                        t2 += 180*30;
                     y = centery - t2/vfac2;    /* screen coord. */
                  }
                  else
                  {
                     t = pt[pt_zhl].lat;        /* y = lattitude */
                     t = (t/120.0 + 45.0) * RAD;
                     t = log(tan((FLOAT)t)) * m_vfactor;
                     if (t < 0.0)               /* round to nearest pixel */
                        t -= 0.5;
                     else
                        t += 0.5;
                     y = centery - (WORD)t;     /* screen coord. */
                  } /* if (type == MAP_FLAT) */

                  t2 = pt[pt_zhl].lam * width;  /* x = longitude */
                  if (t2 < 0)                   /* round to nearest pixel */
                     t2 -= 360*30;
                  else
                     t2 += 360*30;
                  x = centerx + t2/(360*60);    /* screen coord. */

                  if (!new_seg)
                  {
                     if ((x != old_x) || (y != old_y))
                     {                 /* disallow identical adjacent pts */
                        if (ABS(x - old_x) < half_scr_width)
                           Draw(rp, x,y);
                        else
                        {
                           WritePixel(rp, x,y);
                           Move(rp, x,y);
                        }
                     } /* if ((x != old_x) || (y != old_y)) */
                  } /* if (!new_seg) */
                  else
                  {
                     WritePixel(rp, x,y);       /* new segment => complete */
                     Move(rp, x,y);             /* new position! */
                     new_seg = FALSE;
                  } /* else (!new_seg) */

                  old_x = x;                    /* remember old position */
                  old_y = y;
               } /* if (detail_level) */
            } /* for (pt_zhl) */
         } /* for (seg_zhl) */

         if (fhd)                      /* if we opened a file, close it */
         {
            Close(fhd);
            fhd = NULL;
         }
      } /* if (map[].plot) */
   } /* for (map_zhl) */

   TITLE_NORMAL;
   MOUSE_NORMAL;
   IDCMP(NORMAL_IDCMP);
   RMBTRAP_OFF;
}


void draw_boxmap(UWORD type)
{
   WORD x, y, old_x = -1, old_y = -1, width, height;
   WORD box_w, box_h, box_cx, box_cy;
   UWORD anz, map_zhl, seg_zhl;
   ULONG first, last, pt_zhl;
   BOOL new_seg, error, in_view, prev_in_view;
   BPTR fhd = NULL;
   struct arc *seg;
   struct point *pt;
   struct IntuiMessage *msg;
   BOOL abort = FALSE;

   RMBTRAP_ON;
   IDCMP(IDCMP_MOUSEBUTTONS);
   MOUSE_WAIT;
   TITLE_MSG("Drawing map, press RMB to abort");

   get_detail_level();                          /* init. vars */
   width = screen->Width;
   height = screen->Height;
   box_w = box_x2 - box_x1;
   box_h = box_y1 - box_y2;
   box_cx = (box_x1 + box_x2) / 2;
   box_cy = (box_y2 + box_y1) / 2;

   old_maptype = type | MAP_BOX;
   OnMenu(main_wd, FULLMENUNUM(3,1,3));         /* Box zoom */
   OnMenu(main_wd, FULLMENUNUM(3,1,4));

   if (config.cls_before_draw)
      SetRast(rp, config.bg_color);                   /* clear screen */

   for (map_zhl = 0; map_zhl < NUM_MAPS; map_zhl++)   /* do each map type */
   {
      if (config.plotmap[map_zhl] && !abort)    /* if not requested, skip */
      {
         error = FALSE;
         SetAPen(rp, config.mapcolor[map_zhl]); /* initialize color */
         seg = map[map_zhl].seg;

         if (config.loadmap[map_zhl])
            pt = map[map_zhl].pt;
         else
         {
            pt = loadmap_buffer;
            if (!(fhd = get_map_fhd(map_zhl)))
            {
               TITLE_ERROR("Can`t open map file!");
               error = TRUE;
            }
         } /* if (config.loadmap[]) */
                                                /* do each segment */
         for (seg_zhl = 0; seg_zhl < map[map_zhl].nsegs && !error; seg_zhl++)
         {
            /* check for user abort */
            if (msg = (struct IntuiMessage *)GetMsg(main_wd->UserPort))
            {
               if ((msg->Class == IDCMP_MOUSEBUTTONS) && (msg->Code == MENUDOWN))
               {
                  ReplyMsg((struct Message *)msg);    /* user aborted */
                  DisplayBeep(NULL);
                  abort = TRUE;
                  break;
               }
               ReplyMsg((struct Message *)msg);
            } /* if (GetMsg()) */

            if (config.loadmap[map_zhl])        /* map loaded? */
            {
               first = seg[seg_zhl].first;      /* somewhere from the */
               last = seg[seg_zhl].last;        /* whole map */
            }
            else
            {                    /* load whole next segment into buffer */
               anz = seg[seg_zhl].last - seg[seg_zhl].first + 1;
               if (Read(fhd, loadmap_buffer, anz*sizeof(struct point)) !=
                     anz * sizeof(struct point))
               {
                  TITLE_ERROR("Can`t read map file!");
                  error = TRUE;
                  break;                        /* exit seg_zhl-loop */
               }

               first = 0;              /* from beginning of load-buffer */
               last = anz-1;
            } /* if (config.loadmap[]) */

            new_seg = TRUE;            /* we start a new segment */
            prev_in_view = FALSE;      /* obsolete, but better */

            if (seg[seg_zhl].lam_min <= box_x2 &&
                seg[seg_zhl].lam_max >= box_x1 &&
                seg[seg_zhl].lat_min <= box_y1 &&
                seg[seg_zhl].lat_max >= box_y2)
            {
               for (pt_zhl = first; pt_zhl <= last; pt_zhl++)
               {
                  if (pt[pt_zhl].code >= detail_level)
                  {                             /* filter by detail level */
                     x = pt[pt_zhl].lam;
                     y = pt[pt_zhl].lat;

                     /* get status of current point (visable or not) */
                     if ((x >= box_x1 && x <= box_x2) &&
                         (y <= box_y1 && y >= box_y2))
                        in_view = TRUE;
                     else
                        in_view = FALSE;

                     /* calculate screen coordinates */
                     x = centerx + (LONG)(x - box_cx) * width / box_w;
                     y = centery - (LONG)(y - box_cy) * height / box_h;

                     if (in_view)            /* curr. point in view? */
                     {
                        if (!new_seg)
                        {
                           if ((x != old_x) || (y != old_y))
                           {
                              if (!prev_in_view)
                                 Move(rp, old_x,old_y);

                              if (ABS(x - old_x) < half_scr_width)
                                 Draw(rp, x,y);
                              else
                              {
                                 WritePixel(rp, x,y);
                                 Move(rp, x,y);
                              }
                           } /* if ((x != old_x) || (y != old_y)) */
                        } /* if (!new_seg) */
                        else
                        {
                           WritePixel(rp, x,y); /* new segment => complete */
                           Move(rp, x,y);       /* new position */
                           new_seg = FALSE;
                        } /* else (!new_seg) */
                     } /* if (in_view) */
                     else
                     {
                        if (!new_seg)
                        {           /* need not compare x and old_x, this */
                           if (prev_in_view) /* point is out of view, old */
                           {              /* was in view => must differ */
                              if (ABS(x - old_x) < half_scr_width)
                                 Draw(rp, x,y);
                              else
                              {
                                 WritePixel(rp, x,y);
                                 Move(rp, x,y);
                              }
                           } /* if (prev_in_view) */
                        } /* if (!new_seg) */
                        else
                           new_seg = FALSE;
                     } /* else (in_view) */

                     old_x = x;
                     old_y = y;
                     prev_in_view = in_view;
                  } /* if (detail_level) */
               } /* for (pt_zhl) */
            } /* if (segment visible) */
         } /* for (seg_zhl) */

         if (fhd)                /* close file if necassary */
         {
            Close(fhd);
            fhd = NULL;
         }
      } /* if (map[].plot) */
   } /* for (map_zhl) */

   TITLE_NORMAL;
   MOUSE_NORMAL;
   IDCMP(NORMAL_IDCMP);
   RMBTRAP_OFF;
}


void draw_globemap(UWORD type)
{
//
//   get_detail_level();
//
//   old_maptype = type | MAP_SPHERE;
//   OffMenu(main_wd, FULLMENUNUM(3,1,NOSUB));    /* Box */
//   OnMenu(main_wd, FULLMENUNUM(3,2,3));         /* Sphere zoom */
//   OnMenu(main_wd, FULLMENUNUM(3,2,4));
//   OnMenu(main_wd, FULLMENUNUM(3,4,NOSUB));     /* Redraw */
//
//   RMBTRAP_ON;
//   IDCMP(IDCMP_MOUSEBUTTONS);
//   MOUSE_WAIT;
//   TITLE_MSG("Drawing map, press RMB to abort");
//
//   if (config.cls_before_draw)
//      SetRast(rp, config.bg_color);
//
//
//   TITLE_NORMAL;
//   MOUSE_NORMAL;
//   IDCMP(NORMAL_IDCMP);
//   RMBTRAP_OFF;
}

