/*
 *  Copyright 1994-2022 Olivier Girondel
 *  Copyright 2019-2022 Tavasti
 *
 *  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/>.
 */

/* Colrot, Color Rotation

   basic idea of plugin: Show only part of the colors from image,
   and scroll thru colors. Not visible colors are transparent,
   showing stuff happening under. Using lens mode.

   This plugin is 'normal', pretty agressive version of Colrot
*/


#include "context.h"
#include "images.h"

// What size of chunks colorspace is divided
#define DEFAULT_MASK_SIZE   15
// How many colors are visible in each chunk
#define DEFAULT_COLOR_COUNT 5

uint32_t version = 1;
uint32_t options = BO_GFX | BO_LENS | BO_NOT_LENS | BO_IMAGE;
enum LayerMode mode = LM_OVERLAY;
char desc[] = "Show image scrolling colors";
char dname[] = "Image colrot";

static Pixel_t min = 0, max = DEFAULT_COLOR_COUNT;

// Parameters
#define BPP_MASK_SIZE   "mask_size"
#define BPP_COLOR_COUNT "color_count"
static int mask_size = DEFAULT_MASK_SIZE;
static int color_count = DEFAULT_COLOR_COUNT;

#define DEBUG_COLROT


json_t *
get_parameters(const uint8_t fetch_all)
{
  json_t *params = json_object();

  plugin_parameters_add_int(params, BPP_MASK_SIZE, mask_size, 1, 254, 1, "Size of chunks colorspace is divided");
  plugin_parameters_add_int(params, BPP_COLOR_COUNT, color_count, 1, 254, 1, "How many colors are visible in each chunk");

  return params;
}


void
set_parameters(const Context_t *ctx, const json_t *in_parameters)
{
  int reset = plugin_parameter_parse_int_range(in_parameters, BPP_MASK_SIZE, &mask_size) & PLUGIN_PARAMETER_CHANGED;
  reset |= plugin_parameter_parse_int_range(in_parameters, BPP_COLOR_COUNT, &color_count) & PLUGIN_PARAMETER_CHANGED;

  if (reset) {
    min = 0;
    max = color_count;
  }
}


json_t *
parameters(const Context_t *ctx, const json_t *in_parameters, const uint8_t fetch_all)
{
  if (NULL != in_parameters) {
    set_parameters(ctx, in_parameters);
  }

  return get_parameters(fetch_all);
}


void
on_switch_on(Context_t *ctx)
{
  min = 0;
  color_count = max = DEFAULT_COLOR_COUNT;
  mask_size = DEFAULT_MASK_SIZE;
}


void
run(Context_t *ctx)
{
  const Pixel_t *src = ctx->imgf->cur->buff->buffer;
  Pixel_t *dst = passive_buffer(ctx)->buffer;

  for (uint32_t k = 0; k < BUFFSIZE; k++, src++) {
    if (/* max is bigger than min, show values between them */
        ((max > min) && ((*src & mask_size) > min) && ((*src & mask_size) < max))
        /* max is rotated over, show values below max or above min */
        || ((max < min) && (((*src & mask_size) > min) || ((*src & mask_size) < max)))) {
      dst[k] = *src;
    } else {
      dst[k] = 0;
    }
  }

  if (++min > mask_size) {
    min = 0;
  }

  if (++max > mask_size) {
    max = 0;
  }
}
