/*
 * 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;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Icon;

import jnpad.GUIUtilities;
import jnpad.util.Utilities;

/**
 * The Class GradientLabel.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class GradientLabel extends JNPadLabel implements GradientPaintable, Roundable {
  /** The _gradient color1. */
  private Color               _gradientColor1;
  
  /** The _gradient color2. */
  private Color               _gradientColor2;
  
  /** The _orientation. */
  private int                 _orientation     = ORIENTATION_TOP_TO_BOTTOM_CROSS;

  /** The _arc width. */
  private double              _arcWidth;
  
  /** The _arc height. */
  private double              _arcHeight;

  /** Logger. */
  private static final Logger LOGGER           = Logger.getLogger(GradientLabel.class.getName());

  /** UID. */
  private static final long   serialVersionUID = -5260830624227212427L;

  /**
   * Instantiates a new gradient label.
   */
  public GradientLabel() {
    this(Utilities.EMPTY_STRING, null, LEADING);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   */
  public GradientLabel(String text) {
    this(text, null, LEADING);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param horizontalAlignment the horizontal alignment
   */
  public GradientLabel(String text, int horizontalAlignment) {
    this(text, null, horizontalAlignment);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   */
  public GradientLabel(Icon icon) {
    this(null, icon, CENTER);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   */
  public GradientLabel(Icon icon, int horizontalAlignment) {
    this(null, icon, horizontalAlignment);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   */
  public GradientLabel(String text, Icon icon, int horizontalAlignment) {
    super(text, icon, horizontalAlignment);
    setOpaque(false);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param color the color
   */
  public GradientLabel(Color color) {
    this(Utilities.EMPTY_STRING, null, LEADING, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param color the color
   */
  public GradientLabel(String text, Color color) {
    this(text, null, LEADING, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param horizontalAlignment the horizontal alignment
   * @param color the color
   */
  public GradientLabel(String text, int horizontalAlignment, Color color) {
    this(text, null, horizontalAlignment, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param color the color
   */
  public GradientLabel(Icon icon, Color color) {
    this(null, icon, CENTER, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color the color
   */
  public GradientLabel(Icon icon, int horizontalAlignment, Color color) {
    this(null, icon, horizontalAlignment, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color the color
   */
  public GradientLabel(String text, Icon icon, int horizontalAlignment, Color color) {
    this(text, icon, horizontalAlignment, color, color, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(Color color1, Color color2) {
    this(Utilities.EMPTY_STRING, null, LEADING, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(String text, Color color1, Color color2) {
    this(text, null, LEADING, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(String text, int horizontalAlignment, Color color1, Color color2) {
    this(text, null, horizontalAlignment, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(Icon icon, Color color1, Color color2) {
    this(null, icon, CENTER, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(Icon icon, int horizontalAlignment, Color color1, Color color2) {
    this(null, icon, horizontalAlignment, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   */
  public GradientLabel(String text, Icon icon, int horizontalAlignment, Color color1, Color color2) {
    this(text, icon, horizontalAlignment, color1, color2, ORIENTATION_TOP_TO_BOTTOM_CROSS);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param color1 the color1
   * @param color2 the color2
   * @param orientation the orientation
   */
  public GradientLabel(String text, Color color1, Color color2, int orientation) {
    this(text, null, LEADING, color1, color2, orientation);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   * @param orientation the orientation
   */
  public GradientLabel(String text, int horizontalAlignment, Color color1, Color color2, int orientation) {
    this(text, null, horizontalAlignment, color1, color2, orientation);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param color1 the color1
   * @param color2 the color2
   * @param orientation the orientation
   */
  public GradientLabel(Icon icon, Color color1, Color color2, int orientation) {
    this(null, icon, CENTER, color1, color2, orientation);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   * @param orientation the orientation
   */
  public GradientLabel(Icon icon, int horizontalAlignment, Color color1, Color color2, int orientation) {
    this(null, icon, horizontalAlignment, color1, color2, orientation);
  }

  /**
   * Instantiates a new gradient label.
   *
   * @param text the text
   * @param icon the icon
   * @param horizontalAlignment the horizontal alignment
   * @param color1 the color1
   * @param color2 the color2
   * @param orientation the orientation
   */
  public GradientLabel(String text, Icon icon, int horizontalAlignment, Color color1, Color color2, int orientation) {
    super(text, icon, horizontalAlignment);
    _orientation = orientation;
    setGradientColors(color1, color2);
    setOpaque(false);
  }

  /**
   * Gets the gradient color1.
   *
   * @return the gradient color1
   * @see jnpad.ui.GradientPaintable#getGradientColor1()
   */
  @Override
  public Color getGradientColor1() {
    return (_gradientColor1 == null) ? getBackground() : _gradientColor1;
  }

  /**
   * Gets the gradient color2.
   *
   * @return the gradient color2
   * @see jnpad.ui.GradientPaintable#getGradientColor2()
   */
  @Override
  public Color getGradientColor2() {
    return (_gradientColor2 == null) ? getBackground() : _gradientColor2;
  }

  /**
   * Gets the orientation.
   *
   * @return the orientation
   * @see jnpad.ui.Orientable#getOrientation()
   */
  @Override
  public int getOrientation() {return _orientation;}

  /**
   * Sets the color.
   *
   * @param color the new color
   * @see jnpad.ui.GradientPaintable#setColor(java.awt.Color)
   */
  @Override
  public void setColor(Color color) {
    setGradientColors(color, color);
    //setBackground(color); // no hace falta
  }

  /**
   * Sets the gradient color1.
   *
   * @param color1 the new gradient color1
   * @see jnpad.ui.GradientPaintable#setGradientColor1(java.awt.Color)
   */
  @Override
  public void setGradientColor1(Color color1) {
    Color oldGC1 = _gradientColor1;
    _gradientColor1 = color1;
    if ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) { //Keep FindBugs happy
      repaint();
    }
  }

  /**
   * Sets the gradient color2.
   *
   * @param color2 the new gradient color2
   * @see jnpad.ui.GradientPaintable#setGradientColor2(java.awt.Color)
   */
  @Override
  public void setGradientColor2(Color color2) {
    Color oldGC2 = _gradientColor2;
    _gradientColor2 = color2;
    if ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/)) { //Keep FindBugs happy
      repaint();
    }
  }

  /**
   * Sets the gradient colors.
   *
   * @param color1 the color1
   * @param color2 the color2
   * @see jnpad.ui.GradientPaintable#setGradientColors(java.awt.Color, java.awt.Color)
   */
  @Override
  public void setGradientColors(Color color1, Color color2) {
    Color oldGC1 = _gradientColor1;
    Color oldGC2 = _gradientColor2;
    _gradientColor1 = color1;
    _gradientColor2 = color2;
    if ( ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) || //Keep FindBugs happy
         ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/))) { //Keep FindBugs happy
      repaint();
    }
  }

  /**
   * Sets the orientation.
   *
   * @param orientation the new orientation
   * @see jnpad.ui.Orientable#setOrientation(int)
   */
  @Override
  public void setOrientation(int orientation) {
    if (!supportOrientation(orientation))
      return;
    int oldOrientation = _orientation;
    _orientation = orientation;
    if (oldOrientation != orientation) {
      repaint();
    }
  }

  /**
   * Support orientation.
   *
   * @param orientation the orientation
   * @return true, if successful
   * @see jnpad.ui.Orientable#supportOrientation(int)
   */
  @Override
  public boolean supportOrientation(int orientation) {
    switch (orientation) {
      case ORIENTATION_HORIZONTAL:
      case ORIENTATION_VERTICAL:
      case ORIENTATION_TOP_TO_BOTTOM_CROSS:
      case ORIENTATION_BOTTOM_TO_TOP_CROSS:
        return true;
      default:
        return false;
    }
  }

  /**
   * Gets the arc width.
   *
   * @return the arc width
   * @see jnpad.ui.Roundable#getArcWidth()
   */
  @Override
  public double getArcWidth() {return _arcWidth;}

  /**
   * Sets the arc width.
   *
   * @param arcWidth the new arc width
   * @see jnpad.ui.Roundable#setArcWidth(double)
   */
  @Override
  public void setArcWidth(double arcWidth) {
    double oldArcWidth = _arcWidth;
    _arcWidth = arcWidth;
    if (oldArcWidth != arcWidth) {
      repaint();
    }
  }

  /**
   * Gets the arc height.
   *
   * @return the arc height
   * @see jnpad.ui.Roundable#getArcHeight()
   */
  @Override
  public double getArcHeight() {return _arcHeight;}

  /**
   * Sets the arc height.
   *
   * @param arcHeight the new arc height
   * @see jnpad.ui.Roundable#setArcHeight(double)
   */
  @Override
  public void setArcHeight(double arcHeight) {
    double oldArcHeight = _arcHeight;
    _arcHeight = arcHeight;
    if (oldArcHeight != arcHeight) {
      repaint();
    }
  }

  /**
   * Sets the arcs.
   *
   * @param arcWidth the arc width
   * @param arcHeight the arc height
   * @see jnpad.ui.Roundable#setArcs(double, double)
   */
  @Override
  public void setArcs(double arcWidth, double arcHeight) {
    double oldArcWidth = _arcWidth;
    double oldArcHeight = _arcHeight;
    _arcWidth = arcWidth;
    _arcHeight = arcHeight;
    if (oldArcWidth != arcWidth || oldArcHeight != arcHeight) {
      repaint();
    }
  }

  /**
   * Paint component.
   *
   * @param g the g
   * @see jnpad.ui.JNPadLabel#paintComponent(java.awt.Graphics)
   */
  @Override
  protected void paintComponent(Graphics g) {
    Dimension d = getSize();

    try {
      Graphics2D g2D = (Graphics2D) g;

      final Object oldAntialiasing = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
      g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      Paint p = GUIUtilities.getGradientPaint(getGradientColor1(),
                                            getGradientColor2(),
                                            _orientation, d);
      g2D.setPaint(p);

      RoundRectangle2D rect = new RoundRectangle2D.Double(0.0D, 0.0D, d.width, d.height, _arcWidth, _arcHeight);
      g2D.fill(rect);

      g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasing);
    }
    catch (Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }

    super.paintComponent(g);
  }

}
