/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou 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.
 *
 *  lebiniou 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 lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "context.h"


uint32_t version = 0;
uint32_t options = BO_DISPLACE | BO_LENS;
char desc[] = "Tunnel effect";
char dname[] = "Tunnel";

static uint32_t *tunnel;


int8_t
create(Context_t *ctx)
{
  uint16_t di, dj, start;
  float length;

  tunnel = xcalloc(BUFFSIZE, sizeof(uint32_t));

  for (di = 0; di < HWIDTH; di++) {
    start = (uint16_t)(((float)di / (float)HWIDTH) * (float)HHEIGHT);
    length = HEIGHT - 2 * start;
    for (dj = start; dj < (HEIGHT - start); dj++) {
      tunnel[dj * WIDTH + di] = tunnel[(HEIGHT - 1 - dj) * WIDTH + (WIDTH - 1 - di)] =
                                  (uint32_t)((uint16_t)((float)(dj - start) / length * (float)HEIGHT) * WIDTH + (2 * di));
    }
  }

  for (dj = 0; dj < HHEIGHT; dj++) {
    start = (uint16_t)(((float)dj / (float)HHEIGHT) * (float)HWIDTH);
    length = WIDTH - 2 * start;
    for (di = start; di < (WIDTH - start); di++) {
      tunnel[dj * WIDTH + (WIDTH - 1 - di)] = tunnel[(HEIGHT - 1 - dj) * WIDTH + di] =
          (uint32_t)((uint16_t)((float)(di - start) / length * (float)HEIGHT) * WIDTH + ((float)(dj * 2) / HEIGHT) * WIDTH);
    }
  }

  return 1;
}


void
destroy(Context_t *ctx)
{
  xfree(tunnel);
}


void
run(Context_t *ctx)
{
  uint32_t k;
  const Buffer8_t *src = active_buffer(ctx);
  Buffer8_t *dst = passive_buffer(ctx);

  Buffer8_init_mask_3x3(active_buffer(ctx));

  for (k = 0; k < BUFFSIZE; k++) {
    dst->buffer[k] = src->buffer[tunnel[k]];
  }
}
