/*
 *  Copyright 1994-2022 Olivier Girondel
 *  Copyright 2014-2022 Frantz Balinski
 *
 *  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/>.
 */

/*
 * the idea is to simulate a corner reflector
 */

#include "brandom.h"
#include "translation.h"


uint32_t version = 0;
uint32_t options = BO_DISPLACE | BO_LENS | BO_NOT_LENS;
char desc[] = "Reflector-like effect";
char dname[] = "Reflector";

void         on_switch_on(void);
static Map_t zreflector(short, short);
static void  init_params(void);

static Translation_t *t_zreflector;
static int radius, length, ox, oy, onx, ony;


int8_t
create(Context_t *ctx)
{
  if (WIDTH < 2) {
    printf("\r\e[33m[-] zreflector: WIDTH is less than 2 pixels: plugin disabled\e[0m.\n");
    return 0;
  } else {
    if (HEIGHT < 16) { // see init_params() below
      printf("\r\e[33m[-] zreflector: HEIGHT is less than 16 pixels: plugin disabled\e[0m.\n");
      return 0;
    } else {
      ox = (WIDTH  >> 1);
      oy = (HEIGHT >> 1);
      t_zreflector = Translation_new(&zreflector, &init_params);
      return 1;
    }
  }
}


void
destroy(Context_t *ctx)
{
  Translation_delete(t_zreflector);
}


void
run(Context_t *ctx)
{
  Translation_run(t_zreflector, ctx);
}


void
on_switch_on(void)
{
  Translation_batch_init(t_zreflector);
}

static Map_t
zreflector(const short x, const short y)
{
  Map_t m;

  if (onx != 0) {
    int xx  = x - ox;
    int dx  = ((int)(xx + WIDTH) % length) - radius;
    m.map_x = x + dx;
  } else {
    m.map_x = x;
  }

  if (ony != 0) {
    int yy  = y - oy;
    int dy  = ((int)(yy + HEIGHT) % length) - radius;
    m.map_y = y + dy;
  } else {
    m.map_y = y;
  }

  return m;
}


static void
init_params(void)
{
  radius = b_rand_uint32_range(1, (HEIGHT >> 4) + 1); // HEIGHT must be >= 16
  if (radius < 2) {
    radius = 2;
  }

  length = (radius << 1) + 1;

  do {
    onx = b_rand_boolean();
    ony = b_rand_boolean();
  } while ((onx == 0) && (ony == 0));
}
