/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui.plaf;

import java.awt.Color;
import java.awt.image.RGBImageFilter;

/**
 * The Class DarkIconFilter.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class DarkIconFilter extends RGBImageFilter {
  /**
   * in dark LaFs brighten all icons; 0.0f = no change, 1.0f = maximum
   * brightening
   */
  private static final float DARK_ICON_BRIGHTEN = 0.1f;

  /**
   * Filter rgb.
   *
   * @param x the x
   * @param y the y
   * @param color the color
   * @return the int
   * @see java.awt.image.RGBImageFilter#filterRGB(int, int, int)
   */
  @Override
  public int filterRGB(int x, int y, int color) {
    int a = color & 0xff000000;
    int rgb[] = decode(color);
    int inverted[] = invert(rgb);
    int result[] = invertHueBrighten(inverted, DARK_ICON_BRIGHTEN);
    return a | encode(result);
  }

  /**
   * Invert.
   *
   * @param rgb the rgb
   * @return the int[]
   */
  private int[] invert(int[] rgb) {
    return new int[] { 255 - rgb[0], 255 - rgb[1], 255 - rgb[2] };
  }

  /**
   * Invert hue brighten.
   *
   * @param rgb the rgb
   * @param brighten the brighten
   * @return the int[]
   */
  private int[] invertHueBrighten(int[] rgb, float brighten) {
    float hsb[] = new float[3];
    Color.RGBtoHSB(rgb[0], rgb[1], rgb[2], hsb);
    return decode(Color.HSBtoRGB(hsb[0] > 0.5f ? hsb[0] - 0.5f : hsb[0] + 0.5f, hsb[1], hsb[2] + (1.0f - hsb[2]) * brighten));
  }

  /**
   * Decode.
   *
   * @param rgb the rgb
   * @return the int[]
   */
  private int[] decode(int rgb) {
    return new int[] { (rgb & 0x00ff0000) >> 16, (rgb & 0x0000ff00) >> 8, rgb & 0x000000ff };
  }

  /**
   * Encode.
   *
   * @param rgb the rgb
   * @return the int
   */
  private int encode(int[] rgb) {
    return (toBoundaries(rgb[0]) << 16) | (toBoundaries(rgb[1]) << 8) | toBoundaries(rgb[2]);
  }

  /**
   * To boundaries.
   *
   * @param color the color
   * @return the int
   */
  private int toBoundaries(int color) {
    return Math.max(0, Math.min(255, color));
  }

}
