/*
    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"
#include "match.h"

#define MAX_ORDER 1000

#define nclimbers 200
struct {
   Image src;
   image8_t dst;
   int score;
} tiles[nclimbers];
int tiles_ready = 0;
int current_climber = 0;

void step_rule_fuse(int frame, rule_t *p, image8_t *fb)
{
   int i;
   image8_t dest = *fb;
   static int order = 0;
   int bsize;

   switch (iclamp(p->drift, 4)) {
    case 0:
      bsize = p->bsize;
      /* bsize = TILE_SIZE; */
      dest.width = bsize;
      dest.height = bsize;

      for (i = 0; i < 10; i++) {
	 int dest_x = R%(fb->width - bsize);
	 int dest_y = R%(fb->height - bsize);
	 Image *src_img =
	    &global_images[iclamp(R, p->image_window_size)];
	 Image src_rect;
	 image_random_tile(&src_rect, src_img, bsize);
	 dest.p = fb->p + fb->stride * dest_y + dest_x;
	 image8_blit(&src_rect, &dest);
      }
      order = 0.8 * order;
      break;
    case 1:
      bsize = TILE_SIZE;
      dest.width = bsize;
      dest.height = bsize;

      if (1) {
	 int dest_x, dest_y;
	 Image match;
	 int ntries;
	 int tuner;
	 order++;
	 if (order > MAX_ORDER)
	    order = MAX_ORDER;

	 tuner = p->search_time;
	 if (tuner < 0)
	    tuner = 0;
	 else if (tuner > 10)
	    tuner = 10;
	 p->search_time = tuner;

	 ntries = 1 + order/10 * pow(1.5, tuner);

	 dest_x = R%(fb->width - bsize);
	 dest_y = R%(fb->height - bsize);
	 dest.p = fb->p + dest_x + dest_y * fb->stride;

	 image8_match2(&dest, &match,
		       global_images, global_images_small, p->image_window_size,
		       1 + ntries/(SMALL_FACTOR * SMALL_FACTOR), ntries);
	 image8_blit(&match, &dest);
      }
      break;
    case 2:
      bsize = p->bsize;
      if (!tiles_ready) {
	 int i;
	 for (i = 0; i < nclimbers; i++) {
	    int dest_x, dest_y;
	    Image *src_img =
	       &global_images[iclamp(R, p->image_window_size)];
	    image_random_tile(&tiles[i].src, src_img, bsize);

	    dest_x = R%(fb->width - bsize);
	    dest_y = R%(fb->height - bsize);
	    tiles[i].dst.stride = fb->stride;
	    tiles[i].dst.width = bsize;
	    tiles[i].dst.height = bsize;
	    tiles[i].dst.p = fb->p + fb->stride * dest_y + dest_x;
	 }
	 tiles_ready = 1;
      }
      if (1) {
	 int i;
	 int last = current_climber + 10;
	 for (i = current_climber; i < last; i++) {
	    int j = i%nclimbers;
	    if (image8_climb(&tiles[j].dst, &tiles[j].src)) {
	       int dest_x, dest_y;
	       dest_x = R%(fb->width - bsize);
	       dest_y = R%(fb->height - bsize);
	       dest.p = fb->p + dest_x + dest_y * fb->stride;
	    }
	 }
	 for (i = current_climber; i < last; i++) {
	    int j = i%nclimbers;
	    image8_blit(&tiles[j].src, &tiles[j].dst);
	 }
	 current_climber = last;
      }
      break;
    case 3:
      if (1) {
	 static int track = 0;
	 Image src_img =
	    global_images[iclamp(track++, p->image_window_size)];
	 image8_t dst = *fb;
	 if (dst.width < src_img.width) {
	    src_img.pixels += (src_img.width - dst.width) / 2;
	    src_img.width = dst.width;
	 } else {
	    dst.p += (dst.width - src_img.width) / 2;
	    dst.width = src_img.width;
	 }
	 if (dst.height < src_img.height) {
	    src_img.pixels += src_img.stride * ((src_img.height - dst.height) / 2);
	    src_img.height = dst.height;
	 } else {
	    dst.p += dst.stride * ((dst.height - src_img.height) / 2);
	    dst.height = src_img.height;
	 }
	 image8_blit(&src_img, &dst);
	 order = MAX_ORDER;
	 usleep((unsigned long) (1e6 * 0.02));
      }
      break;
   }
}
