/*

   MGRMAP.C

   Oliver Kraus
   kraus@lrs.e-technik.uni-erlangen.de

*/

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "names.h"
#include "bmf.h"
#include "mgrmap.h"

mgrmap_type mgrmap_Open(char *fname, FILE *fp)
{
   mgrmap_type mm;
   mm = (mgrmap_type)malloc(sizeof(mgrmap_struct));
   if ( mm != NULL )
   {
      mm->map = map_Open(fname, fp);
      if ( mm->map != NULL )
      {
         mm->mgr = NULL;
         mm->dpi = 300;
         mm->dest_width = 800L;
         mm->dest_height = 600L;
         mm->ratio_num = 1L;
         mm->ratio_den = 1L;
         mm->upper_skip = 0;
         mm->idf_height = 15;
         mm->tf_height = 30;
         mm->lf_height = 22;
         mm->is_monster = 1;
         mm->is_card = 1;
         return mm;
      }
      free(mm);
   }
   return NULL;
}

void mgrmap_Close(mgrmap_type mm)
{
   if ( mm != NULL )
   {
      if ( mm->map != NULL )
         map_Close(mm->map);
      if ( mm->mgr != NULL )
         mgr_Close(mm->mgr);
      free(mm);
   }
}

void mgrmap_SetDestSize(mgrmap_type mm, long dest_width, long dest_height)
{
   assert(mm != NULL);
   mm->dest_width = dest_width;
   mm->dest_height = dest_height;
}

void mgrmap_SetFontHeight(mgrmap_type mm, long idf_height, long tf_height, long lf_height)
{
   assert(mm != NULL);
   mm->idf_height = idf_height;
   mm->tf_height = tf_height;
   mm->lf_height = lf_height;
}


#define mgrmap_XToMap(mm, x) \
   (mm->x_skip+((((x)-(mm)->x_offset)*(mm)->ratio_num)/(mm)->ratio_den))
#define mgrmap_YToMap(mm, y) \
   ((mm)->mgr->height-(mm)->upper_skip-(((y)-(mm)->y_offset)*(mm)->ratio_num)/(mm)->ratio_den)


int mgrmap_AllocMGR(mgrmap_type mm)
{
   long dest_height_sub;
   int idx;
   bmf_type bmf;
   assert(mm != NULL);
   if ( mm->map == NULL )
      return 0;

   map_CalculateSize(mm->map);
   map_cnt_sprites(mm->map);

   bmf = bmfa_MatchMaxFont(mm->lf_height);

   idx = 0;

   mm->legend_cnt = 0;
   mm->legend_f1_size = 0L;
   mm->legend_f2_size = 0L;
   mm->legend_f3_size = 0L;

   while( map_get_item_typ(idx) >= 0 )
   {
      if ( map_get_item_cnt(idx) > 0 )
      {
         static char s[80];
         long width;

         mm->legend_cnt++;

         sprintf(s, "%ldx-", map_get_item_cnt(idx));
         width = bmf_GetStrWidth(bmf, s);

         if ( mm->legend_f1_size < width )
            mm->legend_f1_size = width;

         sprintf(s, "%s-", map_get_item_id(idx));
         width = bmf_GetStrWidth(bmf, s);

         if ( mm->legend_f2_size < width )
            mm->legend_f2_size = width;

         sprintf(s, "%s--", map_get_item_string(idx));
         width = bmf_GetStrWidth(bmf, s);

         if ( mm->legend_f3_size < width )
            mm->legend_f3_size = width;
      }
      idx++;
   }

   mm->legend_cols = 1;
   mm->legend_rows = 0;
   if ( mm->legend_cnt > 0 )
   {
      mm->legend_cols = mm->dest_width
         /(mm->legend_f1_size+mm->legend_f2_size+mm->legend_f3_size);
      if ( mm->legend_cols <= 0 )
         mm->legend_cols = 1;
      mm->legend_rows = ((mm->legend_cnt+mm->legend_cols-1)/(mm->legend_cols));
   }

   bmf = bmfa_MatchMaxFont(mm->tf_height);

   dest_height_sub = 0L;
   dest_height_sub += bmf_GetHeight(bmf);
   dest_height_sub += bmf_GetHeight(bmf)/2;
   mm->upper_skip = dest_height_sub;

   bmf = bmfa_MatchMaxFont(mm->lf_height);
   dest_height_sub += mm->legend_rows*bmf_GetHeight(bmf);
   dest_height_sub += bmf_GetHeight(bmf)/2;
   mm->lower_skip = dest_height_sub-mm->upper_skip;

   mm->x_skip = mm->dpi/50L;

   mm->curr_width = mm->map->max_x-mm->map->min_x;
   mm->curr_height = mm->map->max_y-mm->map->min_y;

   mm->ratio_num = mm->dest_width-mm->x_skip*2;
   mm->ratio_den = mm->curr_width;

   if ( mm->ratio_num*mm->curr_height >
      mm->ratio_den*(mm->dest_height-dest_height_sub) )
   {
      mm->ratio_num = mm->dest_height-dest_height_sub;
      mm->ratio_den = mm->curr_height;
   }

   mm->x_offset = mm->map->min_x;
   mm->y_offset = mm->map->min_y;

   if ( mm->mgr != NULL )
      mgr_Close(mm->mgr);

   mm->mgr = mgr_Open(
      mm->dest_width,
      (((mm->curr_height)*mm->ratio_num)/mm->ratio_den)+dest_height_sub );
   if ( mm->mgr == NULL )
      return 0;
   mgr_SetFontHeight(mm->mgr, 7);

   mgr_SetLine(mm->mgr,
      0,                             mm->lower_skip,
      mm->dest_width-1, mm->lower_skip);
   mgr_SetLine(mm->mgr,
      0,                             mm->lower_skip,
      0,                             mm->mgr->height-1-mm->upper_skip);
   mgr_SetLine(mm->mgr,
      mm->dest_width-1, mm->mgr->height-1-mm->upper_skip,
      0,                             mm->mgr->height-1-mm->upper_skip);
   mgr_SetLine(mm->mgr,
      mm->dest_width-1, mm->mgr->height-1-mm->upper_skip,
      mm->dest_width-1, mm->lower_skip);
   return 1;
}

void mgrmap_DrawTitle(mgrmap_type mm, char *title)
{
   map_sprite_struct *sprite;
   int is_level_exit = 0;
   int is_bonus_exit = 0;
   long w, y;
   short i;
   char s[80];

   mgr_SetFontHeight(mm->mgr, mm->tf_height);
   y = mm->mgr->height-1-mm->upper_skip+mgr_GetFontHeight(mm->mgr)/2;
   mgr_SetString( mm->mgr, 0, y, title );
   w = mgr_GetStringWidth(mm->mgr, title );
   w += mgr_GetStringWidth(mm->mgr, "    ");

   /* search for nukem buttons */
   mgr_SetFontHeight(mm->mgr, mm->lf_height);
   for( i = 0; i < mm->map->sprite_cnt; i++ )
   {
      sprite = mm->map->sprite_list+i;
      if ( sprite->picnum == NUKEBUTTON )
      {
         if ( sprite->lotag == 32767 || sprite->lotag < 0)
         {
            is_level_exit = 1;
         }
         else
         {
            is_level_exit = 1;
            is_bonus_exit = 1;
            sprintf(s, "exit to %hd", sprite->lotag);
            mgr_SetString( mm->mgr, w, y, s );
            w += mgr_GetStringWidth(mm->mgr, s );
         }
      }
   }
   if ( is_level_exit == 0 )
   {
      sprintf(s, "no level exit    ");
      mgr_SetString( mm->mgr, w, y, s );
   }
}

void mgrmap_DrawLegend(mgrmap_type mm)
{
   long col_width;
   long col, row;
   int idx;
   map_cnt_sprites(mm->map);
   mgr_SetFontHeight(mm->mgr, mm->lf_height);

   col_width = mm->legend_f1_size+mm->legend_f2_size+mm->legend_f3_size;

   idx = 0;

   col = 0;
   row = 1;
   while( map_get_item_typ(idx) >= 0 )
   {
      if ( map_get_item_cnt(idx) > 0 )
      {
         static char s[80];

         sprintf(s, "%ldx", map_get_item_cnt(idx));
         mgr_SetString( mm->mgr,
            col*col_width,
            mm->lower_skip-row*mgr_GetFontHeight(mm->mgr),
            s );

         sprintf(s, "%s", map_get_item_id(idx));
         mgr_SetString( mm->mgr,
            col*col_width+mm->legend_f1_size,
            mm->lower_skip-row*mgr_GetFontHeight(mm->mgr),
            s );

         sprintf(s, "%s", map_get_item_string(idx));
         mgr_SetString( mm->mgr,
            col*col_width+mm->legend_f1_size+mm->legend_f2_size,
            mm->lower_skip-row*mgr_GetFontHeight(mm->mgr),
            s );

         row++;
         if ( row > mm->legend_rows )
         {
            row = 1;
            col++;
         }
      }
      idx++;
   }


}


void mgrmap_DrawWall(mgrmap_type mm, short wallidx)
{
   short wallidx2;
   long x1, y1, x2, y2;

   x1 = mm->map->wall_list[wallidx].x;
   y1 = mm->map->wall_list[wallidx].y;

   wallidx2 = mm->map->wall_list[wallidx].point2;
   x2 = mm->map->wall_list[wallidx2].x;
   y2 = mm->map->wall_list[wallidx2].y;

   if ( mm->map->wall_list[wallidx].nextsector < 0 ||
        mm->map->wall_list[wallidx].nextwall < 0 )
   {
      long r;
      r = mm->dpi/150L;
      /*
      if ( r == 0 )
         r = 1;
      */
      mgr_MakeDiskBrush(mm->mgr, r);
      mgr_SetLineBrush(mm->mgr,
         mgrmap_XToMap(mm, x1),
         mgrmap_YToMap(mm, y1),
         mgrmap_XToMap(mm, x2),
         mgrmap_YToMap(mm, y2) );
   }
   else
   {
      long r;
      r = mm->dpi/400;
      mgr_MakeDiskBrush(mm->mgr, r);
      mgr_SetLineBrush(mm->mgr,
         mgrmap_XToMap(mm, x1),
         mgrmap_YToMap(mm, y1),
         mgrmap_XToMap(mm, x2),
         mgrmap_YToMap(mm, y2) );
   }
}

void mgrmap_DrawSector(mgrmap_type mm, short secnum)
{
   short i, wallnum, wallidx, wallidx2;
   /* long x1, y1, x2, y2; */

   assert( mm != NULL );
   assert( mm->map != NULL );
   assert( mm->mgr != NULL );

   wallnum = mm->map->sec_list[secnum].wallnum;
   wallidx = mm->map->sec_list[secnum].wallptr;
   /*
   x1 = mm->map->wall_list[wallidx].x;
   y1 = mm->map->wall_list[wallidx].y;
   */
   for( i = 0; i < wallnum; i++ )
   {
      mgrmap_DrawWall(mm, wallidx);
      wallidx2 = mm->map->wall_list[wallidx].point2;
      /*
      x2 = mm->map->wall_list[wallidx2].x;
      y2 = mm->map->wall_list[wallidx2].y;

      if ( mm->map->wall_list[wallidx].nextsector < 0 ||
           mm->map->wall_list[wallidx].nextwall < 0 )
      {
         mgr_MakeDiskBrush(mm->mgr, 2);
         mgr_SetLineBrush(mm->mgr,
            mgrmap_XToMap(mm, x1),
            mgrmap_YToMap(mm, y1),
            mgrmap_XToMap(mm, x2),
            mgrmap_YToMap(mm, y2) );
      }
      else
      {
         mgr_SetLine(mm->mgr,
            mgrmap_XToMap(mm, x1),
            mgrmap_YToMap(mm, y1),
            mgrmap_XToMap(mm, x2),
            mgrmap_YToMap(mm, y2) );
      }
      */
      wallidx = wallidx2;
      /*
      x1 = x2;
      y1 = y2;
      */
   }
}

void mgrmap_DrawLines(mgrmap_type mm)
{
   short i;
   assert( mm != NULL );
   assert( mm->map != NULL );
   /*
   for( i = 0; i < mm->map->sec_cnt; i++ )
   {
      mgrmap_DrawSector(mm, i);
      printf("sector %hd/%hd\r", i, mm->map->sec_cnt );
   }
   */
   for( i = 0; i < mm->map->wall_cnt; i++ )
   {
      mgrmap_DrawWall(mm, i);
      printf("wall %hd/%hd\r", i+1, mm->map->wall_cnt ); fflush(stdout);
   }

}

void mgrmap_DrawSprites(mgrmap_type mm)
{
   int idx, cnt;
   char s[20];
   map_sprite_struct *sprite;
   short i;
   assert( mm != NULL );
   assert( mm->map != NULL );
   mgr_SetFontHeight(mm->mgr, mm->idf_height);
   cnt = 1;
   for( i = 0; i < mm->map->sprite_cnt; i++ )
   {
      sprite = mm->map->sprite_list+i;
      idx = map_get_info_idx(sprite->picnum, sprite->pal);
      if ( idx >= 0 )
      {
         long w;

         if ( map_get_item_typ(idx) == MAP_TYP_MONSTER &&
              mm->is_monster == 0 )
            continue;

         if ( map_get_item_typ(idx) == MAP_TYP_CARD &&
              mm->is_card == 0 )
            continue;

         /* sprintf(s, "%hd", sprite->picnum); */
         sprintf(s, "%s", map_get_item_id(idx));
         w = mgr_GetStringWidth(mm->mgr, s);
         mgr_SetString( mm->mgr,
            mgrmap_XToMap(mm, sprite->x)-w/2,
            mgrmap_YToMap(mm, sprite->y),
            s
         );
         printf("sprite %d            \r", cnt++ ); fflush(stdout);
      }
      /*
      else if ( sprite->picnum >= 1240 )
      {
         sprintf(s, "%hd", sprite->picnum);
         mgr_SetString( mm->mgr,
            mgrmap_XToMap(mm, sprite->x),
            mgrmap_YToMap(mm, sprite->y),
            s
         );
      }
      */
   }
}
