/*
    bomb - automatic interactive visual stimulation
    Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "defs.h"
#include "image.h"
#include "image_db.h"

void
step_rule_rug_image(int frame, rule_t *p, image8_t *fb) {
   int x,y,bx,by;	
   board_t *s_heat_board, *d_heat_board;
   board_t *s_image_board, *d_image_board;
   u_char *lp;

   s_heat_board=&board[dbuf];
   d_heat_board=&board[1-dbuf];

   s_image_board=&board2[0];
   
   dbuf = 1-dbuf;

   for (y=1;y<=YSIZE;y++) {
      lp = fb->p + (fb->stride * (y - 1));
      for (x=1;x<=XSIZE;x++) {
	 int heat, t;
	 heat = ((((*s_heat_board)[x  ][y-1])+
		  ((*s_heat_board)[x-1][y  ]<<1)+
		  ((*s_heat_board)[x  ][y  ]<<1)+
		  ((*s_heat_board)[x+1][y  ]<<1)+
		  ((*s_heat_board)[x  ][y+1])) >> 3);
	 if (heat < 0) {
	    if (p->floor)
	       heat = 0;	 /* hm, just &mask? */
	    else if (p->randomized_underflow)
	       heat = R;
	 }
	 t = (*s_image_board)[x][y];
	 heat += t;
	 heat += p->speed;
	 heat &= p->mask;
	 (*d_heat_board)[x][y]= heat;
	 if (p->remap)
	    heat = remap[heat];
	 *(lp++) = heat;
#if 0
	 /* some kind of non-linearity could be cool, adjusted to mask,
	    what is the distribution of heat values in a rug? */
	 *(lp++) = 20 * log(1+t);
#endif
      }
   }
}









int current_image = 0;
struct dirent **image_dir;
int image_dir_len;
Image global_images[N_RAM_IMAGES];
Image global_images_small[N_RAM_IMAGES];
Image *global_image;
image8_t small_pattern;
u_char sd_pix[SMALL_SIZE * SMALL_SIZE];

int
gray(Pixel p)
{
   int g = ((p & 0xff) + ((p & 0xff00) >> 8) + ((p & 0xff0000) >> 16));
   return g;
}


void
drive_with_image(int image_num)
{
   int i, j;
   board_t *s_image_board, *d_image_board;
   int w, h, s;
   Pixel *p;

   image_num = iclamp(image_num, N_RAM_IMAGES);

   s_image_board=&board2[0];
   d_image_board=&board2[1];

   global_image = &global_images[image_num];

   w = global_image->width;
   h = global_image->height;
   p = global_image->pixels;
   s = global_image->stride;
   for (i = 0; i < YSIZE+2; i++) {
      for (j =  0; j < XSIZE+2; j++) {
	 int g = gray(p[(i * h / (YSIZE+2)) * s + (j * w / (XSIZE+2))]);
	 ((*s_image_board)[j][i]) = g >> 8;
	 ((*d_image_board)[j][i]) = g >> 8;
      }
   }
}

void
invert_board()
{
   board_t *s_image_board, *d_image_board;
   int i, j;
   s_image_board=&board2[0];
   d_image_board=&board2[1];

   for (i = 0; i < YSIZE+2; i++) {
      for (j =  0; j < XSIZE+2; j++) {
	 (*s_image_board)[j][i] *=  -1;
	 (*d_image_board)[j][i] *=  -1;
      }
   }
}

void rotate_images()
{
   int i;
   Image bt;
   Image st;
   int last = N_RAM_IMAGES - 1;

   bt = global_images[last];
   st = global_images_small[last];

   for (i = last; i > 0; i--) {
      global_images[i] = global_images[i - 1];
      global_images_small[i] = global_images_small[i - 1];
   }
   global_images[0] = bt;
   global_images_small[0] = st;
}


#include <dirent.h>

int isimage(const struct dirent *d) {
   return d->d_name[0] != '.';
}

void file_to_image(int file_num, int image_num)
{
   char buf[PATH_MAX];
   extern int tiles_ready;
   tiles_ready = 0;
   image_num = iclamp(image_num, N_RAM_IMAGES);
   if (1 > image_dir_len) {
      int x, y;
      Image *im = &global_images[image_num];
      image_allocate(im, 100, 100);
      for (x = 0; x < 100; x++)
	 for (y = 0; y < 100; y++)
	    im->pixels[im->stride * y + x] =
	       (((x>>3) + (y>>3)) & 1) ? 0 : -1;
   } else {
      file_num = iclamp(file_num, image_dir_len);
      sprintf(buf, "suck/%s", image_dir[file_num]->d_name);
      /* printf("buf=%s image_num=%d\n", buf, image_num); */
      if (TCL_ERROR == image_read(global_images + image_num, buf))
	 return file_to_image(file_num + 1, image_num);
   }
   image_allocate(global_images_small + image_num,
		  global_images[image_num].width / SMALL_FACTOR,
		  global_images[image_num].height / SMALL_FACTOR);
   image_filter_down(global_images + image_num,
		     global_images_small + image_num);
}

void random_image_set()
{
   int i;
   for (i = 0; i < N_RAM_IMAGES; i++)
      file_to_image(R, i);
}


int init_images()
{
   int i;

   small_pattern.width = SMALL_SIZE;
   small_pattern.height = SMALL_SIZE;
   small_pattern.stride = SMALL_SIZE;
   small_pattern.p = sd_pix;

   image_dir_len = scandir("suck", &image_dir, isimage, alphasort);

   if (1 > image_dir_len)
      fprintf(stderr, "no images found, using checker-board\n");

   for (i = 0; i < N_RAM_IMAGES; i++) {
      image_init(&global_images[i]);
      image_init(&global_images_small[i]);
   }

   if (!getenv("quick"))
      random_image_set();
}
