/*
 * $Id: BarGraph.java,v 1.6 2007-03-11 20:40:58 larry Exp $ 
 */
package com.representqueens.spark;

/*
 * 
 * Copyright 2006 Larry Ogrodnek
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

/**
 * Bargraph generation.
 * 
 * @author Larry Ogrodnek <larry@cheesesteak.net>
 * @version $Revision: 1.6 $ $Date: 2007-03-11 20:40:58 $
 */
public class BarGraph
{
  public static final int DEFAULT_WIDTH = 100;
  public static final int DEFAULT_HEIGHT = 25;
  
  public static final int DEFAULT_SPACING = 2;
  
  public static final SizeParams DEFAULT_SIZE = new SizeParams(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_SPACING);
  
  public static final Color DEFAULT_COLOR = Color.GRAY;
  public static final Color DEFAULT_HIGH_COLOR = Color.BLACK;
  public static final Color DEFAULT_LAST_COLOR = Color.RED;
  
  
  /**
   * Create a Bargraph from an array of numbers, using default colors and sizes.
   *    
   * @param data Array of Number Objects.
   * 
   * @return BufferedImage containing a Bargraph of data.
   */
  public static BufferedImage createGraph(final Number[] data)
  {
    return createGraph(data, DEFAULT_SIZE, DEFAULT_COLOR, DEFAULT_HIGH_COLOR, DEFAULT_LAST_COLOR);
  }
  
  
  /**
   * Create a Bargraph.
   * 
   * @param data Array of Number Objects to graph.
   * @param size SizeParams specifying graph size attributes.
   * @param color main graph color
   * @param highColor color for above average data points (or null).
   * @param lastColor color for last data point (or null).
   * 
   * @return BufferedImage containing a Bargraph of data.
   */
  public static BufferedImage createGraph(final Number[] data, final SizeParams size, final Color color, final Color highColor, final Color lastColor)
  {
    return createGraph(data, size, color, highColor, lastColor, null);
  }
  
  /**
   * Create a Bargraph.
   * 
   * @param data Array of Number Objects to graph.
   * @param size SizeParams specifying graph size attributes.
   * @param color main graph color
   * @param highColor color for above average data points (or null).
   * @param lastColor color for last data point (or null).
   * @param background background color, or null for transparency.
   * 
   * @return BufferedImage containing a Bargraph of data.
   */
  public static BufferedImage createGraph(final Number[] data, final SizeParams size, final Color color, final Color highColor, final Color lastColor, final Color background) 
  {
    final BufferedImage bi = new BufferedImage(size.getWidth(), size.getHeight(), BufferedImage.TYPE_INT_ARGB);
    
    if (data == null || data.length < 1)
    {
      return bi;
    }
  
    final Graphics2D g = bi.createGraphics();
    //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
    if (background != null)
    {
      g.setBackground(background);
      g.clearRect(0, 0, size.getWidth(), size.getHeight());
    }    
    
    final float d = GraphUtils.getDivisor(data, size.getHeight());
    
    final int a = getAvg(data);
    final int w = (size.getWidth() - (size.getSpacing() * data.length))/ data.length;
    
    int x = 0; 
    final int y = 0;
    
    int c = 0;
    
    for (final Number i : data)
    {
      final int h = (int) (i.floatValue() / d);
      
      if (c == (data.length - 1) && lastColor != null)
      {
        g.setPaint(lastColor);
      }
      else if (i.intValue() < a || (highColor == null))
      {
        g.setPaint(color);
      }
      else
      {
        g.setPaint(highColor);
      }
      
      g.fill(new Rectangle2D.Double(x, y + (size.getHeight() - h), w, i.intValue() / d));
      x+=(w + size.getSpacing());
      c++;
    }
    
    return bi;
  }
  
  private static final int getAvg(final Number[] data)
  {
    int total = 0;
    
    for (final Number i : data)
    {
     total += i.intValue(); 
    }
    
    return (total / data.length);
  }
}
