/*----------------------------------------------------------------------------*
 | This file is part of DEU (Doom Editing Utilities), created by the DEU team:|
 | Raphael Quinet, Brendon Wyber, Ted Vessenes and others.  See README.1ST or |
 | the "about" dialog box for full credits.                                   |
 |                                                                            |
 | DEU is an open project: if you think that you can contribute, please join  |
 | the DEU team.  You will be credited for any code (or ideas) included in    |
 | the next version of the program.                                           |
 |                                                                            |
 | If you want to make any modifications and re-distribute them on your own,  |
 | you must follow the conditions of the DEU license.  Read the file LICENSE  |
 | in this directory or README.1ST in the top directory.  If do not have a    |
 | copy of these files, you can request them from any member of the DEU team, |
 | or by mail: Raphael Quinet, Rue des Martyrs 9, B-4550 Nandrin (Belgium).   |
 |                                                                            |
 | This program comes with absolutely no warranty.  Use it at your own risks! |
 *----------------------------------------------------------------------------*

 W_TEMPLA.C - WAD templates and special texture names

*/

/* the includes */
#include "deu.h"
#include "d_misc.h"
#include "d_config.h"
#include "w_levels.h"
#include "w_templa.h"

static char *specialfloors[] =
{
  "__FLOOR", /* 0 */
  "__CEIL",  /* 1 */
  "__AUTO",  /* 2 */
};
#define NUM_SPECIAL_F   3

static char *specialwalls[] =
{
  "__WALL",  /* 0 */
  "__LOWER", /* 1 */
  "__UPPER", /* 2 */
  "__DOOR",  /* 3 */
  "__DTRAK", /* 4 */
  "__LIFT",  /* 5 */
  "__STEP",  /* 6 */
  "__SWITCH" /* 7 */
};
#define NUM_SPECIAL_W   8


/*
   Check if a floor/ceiling texture is "special" (placeholder).
*/

Bool IsSpecialFTexture(char *texname)
{
  int i;

  for (i = 0; i < NUM_SPECIAL_F; i++)
    if (!stricmp(texname, specialfloors[i]))
      return TRUE;
  return FALSE;
}


/*
   Check if a wall texture is "special" (placeholder).
*/

Bool IsSpecialWTexture(char *texname)
{
  int i;

  for (i = 0; i < NUM_SPECIAL_W; i++)
    if (!stricmp(texname, specialwalls[i]))
      return TRUE;
  return FALSE;
}


/*!

*/

static Int16 GetAdjacentSector(LevelPtr level, Int16 sector)
{
  Int16  ld, s;
  Int16  sd1, sd2;
  SelPtr adjs;

  /* get the list of adjacent sectors in adjs */
  adjs = NULL;
  for (ld = level->num_linedefs - 1; ld >= 0; ld--)
    {
      sd1 = level->linedefs[ld].sidedef1;
      sd2 = level->linedefs[ld].sidedef2;
      if (sd1 < 0 || sd2 < 0)
        continue;
      if (level->sidedefs[sd1].sector == sector)
        s = level->sidedefs[sd2].sector;
      else if (level->sidedefs[sd2].sector == sector)
        s = level->sidedefs[sd1].sector;
      else
        s = -1;
      if (s >= 0 && !IsSelected(adjs, s))
        SelectObject(&adjs, s);
    }
  UnSelectObject(&adjs, sector);
  /* get the first sector which is not special */
  while (adjs != NULL)
    {
      s = adjs->objnum;
      if (level->sectors[s].floort[0] == '#' || level->sectors[s].ceilt[0] == '#')
        UnSelectObject(&adjs, s);
      else
        {
          ForgetSelection(&adjs);
          return s;
        }
    }
  return -1;
}


/*
   Replace special floor/ceiling textures with their real value.
   Note: This routine may fail and return a non-null slist if one or several
         sectors have __AUTO textures and either have no neighbours or are
         completely surrounded by sectors with special textures and which
         are not in slist (so that they cannot be updated first).
*/

void UpdateSpecialFTextures(LevelPtr level, SelPtr *slist)
{
  int     i, t;
  Int16   s, as;
  char   *texname;
  SelPtr  rej;
  int     numrej, oldrej;

  if (slist == NULL)
    return;
  rej = NULL;
  numrej = 0;
  oldrej = 0;
  while (*slist != NULL)
    {
      s = (*slist)->objnum;
      as = -1;
      for (t = 1; t <= 2; t++)
        {
          if (t == 1)
            texname = level->sectors[s].floort;
          else
            texname = level->sectors[s].ceilt;
          for (i = 0; i < NUM_SPECIAL_F; i++)
            if (!stricmp(texname, specialfloors[i]))
              break;
          for (i = 0; i < NUM_SPECIAL_F; i++)
            if (!stricmp(texname, specialfloors[i]))
              break;
          switch (i)
            {
            case 0: /* __FLOOR */
              strncpy(texname, Config.floorTexture, 8);
              break;
            case 1: /* __CEIL */
              strncpy(texname, Config.ceilingTexture, 8);
              break;
            case 2: /* __AUTO */
              if (as < 0)
                as = GetAdjacentSector(level, s);
              if (as >= 0)
                {
                  if (t == 1)
                    strncpy(texname, level->sectors[as].floort, 8);
                  else
                    strncpy(texname, level->sectors[as].ceilt, 8);
                }
              else
                {
                  /* try again later */
                  SelectObject(&rej, s);
                  numrej++;
                  t = 3; /* hack */
                }
              break;
            }
        }
      UnSelectObject(slist, s);
      if (*slist == NULL && rej != NULL)
        {
          /* try again with the sectors that had no suitable neighbours */
          *slist = rej;
          rej = NULL;
          /* ... but not if the list has not changed since the last try */
          if (numrej == oldrej)
            return;
          oldrej = numrej;
          numrej = 0;
        }
    }
}


/*
   Replace special wall textures with their real value.
*/

void UpdateSpecialWTextures(LevelPtr level, SelPtr *sdlist)
{
  int    i, t;
  Int16  sd;
  char  *texname;

  if (sdlist == NULL)
    return;
  while (*sdlist != NULL)
    {
      sd = (*sdlist)->objnum;
      for (t = 1; t <= 3; t++)
        {
          switch (t)
            {
            case 1:
              texname = level->sidedefs[sd].tex1;
              break;
            case 2:
              texname = level->sidedefs[sd].tex2;
              break;
            case 3:
              texname = level->sidedefs[sd].tex3;
              break;
            }
          for (i = 0; i < NUM_SPECIAL_W; i++)
            if (!stricmp(texname, specialwalls[i]))
              break;
          switch (i)
            {
            case 0: /* __WALL */
              strncpy(texname, Config.wallTexture, 8);
              break;
            case 1: /* __LOWER */
              strncpy(texname, Config.lowerTexture, 8);
              break;
            case 2: /* __UPPER */
              strncpy(texname, Config.upperTexture, 8);
              break;
            case 3: /* __DOOR */
              strncpy(texname, Config.doorFaceTexture, 8);
              break;
            case 4: /* __DTRAK */
              strncpy(texname, Config.doorTrakTexture, 8);
              break;
            case 5: /* __LIFT */
              strncpy(texname, Config.liftFaceTexture, 8);
              break;
            case 6: /* __STEP */
              strncpy(texname, Config.stepFaceTexture, 8);
              break;
            case 7: /* __SWITCH */
              strncpy(texname, Config.switchTexture, 8);
              break;
            }
        }
      UnSelectObject(sdlist, sd);
    }
}

/* end of file */
