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

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;

import javax.swing.Icon;

import jnpad.ui.plaf.LAFUtils;
import jnpad.util.Platform;

/**
 * Esta clase proporciona un icono que está compuesto por un número de otros
 * iconos.
 * 
 * @version 0.3
 * @since   jNPad v0.1
 */
public class CompositeIcon implements Icon {
  private static final int
      RAISED                          = 0,
      EMPTY = 1,
      LOWERED = 2;

  /** The Constant HORIZONTAL. */
  public static final int  HORIZONTAL = 0;
  
  /** The Constant VERTICAL. */
  public static final int  VERTICAL   = 1;

  private int              _iconHeight;
  private int              _iconWidth;
  private int[]            _borders;
  private int              _orientation;
  private Icon[]           _icons;
  private Icon             _mainIcon;
  private int              _gap;

  /**
   * Crear un icono compuesto.
   * 
   * @param icons los iconos que forman parte del icono compuesto.
   * @param gap el espacio entre los iconos.
   * @param orientation la orientacion: HORIZONTAL o VERTICAL.
   */
  public CompositeIcon(Icon[] icons, int gap, int orientation) {
    this(icons);
    if ((icons.length <= 1) || (gap <= 0)) {
      return;
    }
    _gap = gap;
    _orientation = orientation;
    for (int i = 0; i < icons.length; ++i) {
      switch (orientation) {
        case HORIZONTAL:
          if (i == 0) {
            _iconWidth = 0;
          }
          _iconWidth += icons[i].getIconWidth();
          if (icons.length - 1 <= i) {
            continue;
          }
          _iconWidth += gap;
          break;
        case VERTICAL:
          if (i == 0) {
            _iconHeight = 0;
          }
          _iconHeight += icons[i].getIconHeight();
          if (icons.length - 1 <= i) {
            continue;
          }
          _iconHeight += gap;
          break;
        default:
          throw new IllegalArgumentException();
      }
    }
  }

  /**
   * Crear un icono compuesto.
   * 
   * @param icons los iconos que forman parte del icono compuesto.
   */
  public CompositeIcon(Icon[] icons) {
    _icons = icons;
    _orientation = -1;
    _borders = new int[icons.length];
    for (int k = 0; k < icons.length; ++k) {
      _iconWidth = Math.max(_iconWidth, icons[k].getIconWidth());
      _iconHeight = Math.max(_iconHeight, icons[k].getIconHeight());
      _borders[k] = (((icons[k] instanceof IconClickTarget) && (!Platform.isMac)) ? RAISED : EMPTY);
    }
  }

  /**
   * Sets the main icon.
   *
   * @param icon the new main icon
   */
  public void setMainIcon(Icon icon) {
    _mainIcon = icon;
  }

  /**
   * Gets the main icon.
   *
   * @return the main icon
   */
  public Icon getMainIcon() {
    return _mainIcon;
  }

  /**
   * Checks for main icon.
   *
   * @return true, if successful
   */
  public boolean hasMainIcon() {
    return _mainIcon != null;
  }

  /**
   * Gets the icon height.
   *
   * @return the icon height
   * @see javax.swing.Icon#getIconHeight()
   */
  @Override
  public int getIconHeight() {
    return _iconHeight;
  }

  /**
   * Gets the icon width.
   *
   * @return the icon width
   * @see javax.swing.Icon#getIconWidth()
   */
  @Override
  public int getIconWidth() {
    return _iconWidth;
  }

  /**
   * Paint icon.
   *
   * @param c the Component
   * @param g the Graphics
   * @param x the x
   * @param y the y
   * @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int)
   */
  @Override
  public void paintIcon(Component c, Graphics g, int x, int y) {
    int dx = 0;
    int dy = 0;

    for (int i = 0; i < _icons.length; ++i) {
      Icon icon = _icons[i];
      int iw = icon.getIconWidth();
      int ih = icon.getIconHeight();
      int ix = x + (_iconWidth - iw) / 2;
      int iy = y + (_iconHeight - ih) / 2;

      switch (_orientation) {
        case HORIZONTAL:
          ix = x + dx;
          dx += iw + _gap;
          break;
        case VERTICAL:
          iy = y + dy;
          dy += ih + _gap;
          break;
        default: //Keep FindBugs happy
          break;
      }

      Rectangle rect;
      switch (_borders[i]) {
        case RAISED:
          icon.paintIcon(c, g, ix, iy);
          rect = new Rectangle(ix, iy, iw, ih);
          paintBorder(g, rect, true);
          break;
        case EMPTY:
          icon.paintIcon(c, g, ix, iy);
          break;
        case LOWERED:
          ++ix;
          ++iy;
          rect = new Rectangle(ix, iy, iw, ih);
          icon.paintIcon(c, g, ix, iy);
          paintBorder(g, rect, false);
          break;
      }
    }
  }

  /**
   * Paint border.
   *
   * @param g the Graphics
   * @param r the Rectangle
   * @param raised the raised
   */
  private void paintBorder(Graphics g, Rectangle r, boolean raised) {
    Color color = LAFUtils.getPanelBackground();
    Color color1;
    Color color2;
    if (raised) {
      color1 = color.brighter();
      color2 = color.darker();
    }
    else {
      color1 = color.darker();
      color2 = color.brighter();
    }
    g.setColor(color1);
    g.drawLine(r.x, r.y, r.x, r.y + r.height - 1);
    g.drawLine(r.x, r.y, r.x + r.width - 1, r.y);
    g.setColor(color2);
    g.drawLine(r.x + r.width - 1, r.y, r.x + r.width - 1, r.y + r.height - 1);
    g.drawLine(r.x, r.y + r.height - 1, r.x + r.width - 1, r.y + r.height - 1);
  }

  /**
   * Find hit.
   *
   * @param p the p
   * @return the icon
   */
  public Icon findHit(Point p) {
    for (Icon icon : _icons) {
      if (!(icon instanceof IconClickTarget)) {
        continue;
      }
      IconClickTarget iconClickTarget = (IconClickTarget) icon;
      if (iconClickTarget.isHit(p)) {
        return iconClickTarget.getTarget();
      }
    }
    return null;
  }

}
