package graphics.charts;

import gui.ClosableJFrame;

import javax.swing.*;
import java.awt.*;

/**
 * PieGraph implements the Paintable interface and uses the update
 * method to draw a pie graphics.graph on a Canvas.
 * Requires an instance of DoubleData in order
 * to be constructed.<BR>
 * Global variables:
 * <UL>
 * <LI> DoubleData: instance of DoubleData so the graphics.graph is drawn
 *     with the proper data
 *  <LI> CIRCLESIZE: 360 degrees in a circle
 *  <LI> startAngle: the point at which to begin drawing the pie graphics.graph
 *  <LI> radius: the radius of the pie graphics.graph
 *  <LI> centerX: the X coordinate of the center of the pie graphics.graph
 *  <LI> centerY: the Y coordinate of the center of the pie graphics.graph
 * </UL>
 *
 * @author  Allison McHenry
 * @author  Douglas Lyon, PhD
 * @since   JDK 1.3
 */


public class PieGraph
    extends JComponent implements Paintable {
//GLOBAL VARIABLES
  private static final double CIRCLESIZE = 360.0;
  private double startAngle = 0;
  private int centerX = 10;
  private int centerY = 10;
  private String labels[] = {
    "Apples",
    "Oranges",
    "Bananas",
    "Papayas"
  };
  private DoubleData dd;
  private int radius = 0;

//CONSTRUCTORS

  /**
   *    Default constructor, used to instantiate an instance of PieGraph by
   *    the testing class
   *    @param _dd      instance of DoubleData used to draw the graphics.graph
   */
  public PieGraph() {
    this(400, 400);
  }

  /**
   *    Constructor used to set just the radius
   *
   *    @param _radius      The pie radius
   */
  public PieGraph(int _radius) {
    this(_radius * 2, _radius * 2);
  }

  /**
   *    Constructor used to set just the radius
   *
   *    @param w    the image width
   *    @param h    the image height
   */
  public PieGraph(int w, int h) {
    setSize(w, h);
    setBackground(Color.white);
    dd = new DoubleData(w, h);
  }

  public Dimension getPreferredSize() {
    return new Dimension(dd.getWidth(), dd.getHeight());
  }

  public Dimension getMinimumSize() {
    return new Dimension(dd.getWidth(), dd.getHeight());
  }

  /**
   *    Draws the legend on the top canvas. The labels are passed in
   *   and the percentage of the pie that each slice takes up
   *    is calculated. The label color is determined by mapping
   *    the number of the label to the corresponding color value
   *    in the ColorUtils map. TO FIX: if the number of labels passed
   *    does not correspond to the number of data points, the
   *    labels won't match up correctly. This should throw an
   *    exception.
   *
   *    @param s    Array of strings which correspond to each slice
   *    @return p   Panel with the labels drawn on it
   *    @see        DoubleData.#calculatePercentage
   *    @see        java.awt.Panel
   *    @see        java.awt.Label
   */
  private JPanel getLegendPanel() {
    JPanel p = new JPanel();
    String percentages[] = calculatePercentage();
    ColorUtils cu = new ColorUtils(labels.length);
    p.setBackground(Color.white);
    p.setLayout(new GridLayout(0, 2));
    for (int i = 0; i < labels.length; i++) {
      JLabel text = new JLabel(labels[i]);
      JLabel pct = new JLabel(percentages[i]);
      text.setForeground(cu.getColor(i));
      pct.setForeground(cu.getColor(i));
      p.add(text);
      p.add(pct);
    }
    return p;
  }

  /**
   *    Constructor used to set the data, labels and title only
   *
   *    @param _x           The data to graphics.graph
   *    @param _labels      The labels which correspond to the data elements
   *    @param _title       The title of the graphics.graph
   */
  public PieGraph(DoubleData _dd) {
    dd = _dd;
    setSize(dd.getWidth(), dd.getHeight());
  }


//BEGIN SETTER METHODS


  /**
   *    Sets the center of the pie graphics.graph X and Y coordinates.
   *
   *    @param _x   X coordinate of center of pie graphics.graph
   *    @param _y   Y coordinate of center of pie graphics.graph
   */
  public void setLocation(int x, int y) {
    centerX = x;
    centerY = y;
  }

  public void setValues(double[] _x) {
    dd.setXVals(_x);
  }


  /**
   *    Sets the point on the circle where the pie should begin to be drawn.
   *
   *    @param _startAngle      Pie graphics.graph start angle
   */
  public void setStartAngle(double _startAngle) {
    startAngle = _startAngle;
  }

  /**
   *    Sets the X coordinate of the center of the pie graphics.graph.
   *
   *    @param _centerX     X-coordinate of center of pie
   */

  public void setCenterX(int _centerX) {
    centerX = _centerX;
  }

  /**
   *    Sets the Y coordinate of the center of the pie graphics.graph.
   *
   *    @param _centerY     Y-coordinate of center of pie
   */
  public void setCenterY(int _centerY) {
    centerY = _centerY;
  }


  /**
   *    Sets pie graphics.graph labels. Each label should correspond to one data point in the X array.
   *
   *    @param _labels  Pie graphics.graph labels
   */
  public void setLabels(String[] _labels) {
    labels = _labels;
  }

  public void setRadius(int _radius) {
    radius = _radius;
  }

  /**
   *    Gets the pie graphics.graph radius.
   *
   *    @return radius  Pie graphics.graph radius
   */
  public int getRadius() {
    if (radius == 0) {
      return (Math.max(getSize().width, getSize().height)) / 2;
    } else {
      return radius;
    }
  }

  /**
   *    Gets the point on the circle where the pie should begin to be drawn.
   *
   *    @return _startAngle     Pie graphics.graph start angle
   */
  public double getStartAngle() {
    return startAngle;
  }

  /**
   *    Gets the X coordinate of the center of the pie graphics.graph.
   *
   *    @return centerX     X-coordinate of center of pie
   */
  public int getCenterX() {
    return centerX;
  }

  /**
   *    Gets the Y coordinate of the center of the pie graphics.graph.
   *
   *    @return centerY     Y-coordinate of center of pie
   */
  public int getCenterY() {
    return centerY;
  }

  /**
   *    Gets pie graphics.graph labels. Each label should correspond to one data point in the X array.
   *
   *    @return _labels Pie graphics.graph labels
   */
  public String[] getLabels() {
    return labels;
  }


  //UTILITY METHODS


  /**
   *    Calls the update method to paint this data from DoubleData onto
   *    an image. It calls update instead of overriding the paint method
   *    directly because "paint" is a specialized method name and it
   *    conflicts with the "paint" method in the PieGraphCanvas class.
   *
   *    @param g    Graphics context for drawing
   *    @see        PieGraphPanel.#update
   */
  public void paint(Graphics g) {
    drawGraph(g);
  }


  /**
   *    Draws the circle for the pie graphics.graph. The data to graphics.graph
   *    is determined by the values in the X array. The values in
   *    the Y array are irrelevant.StartAngle is a global variable
   *    from DoubleData which defaults to zero (top of the pie).
   *
   *    @param g    Graphics context for drawing
   *    @see        PieGraph.#paint
   *    @see        DoubleData.#getSumX
   *    @see        ColorUtils.#getColor
   *    @see        java.awt.Graphics.#fillArc
   */

  private void drawGraph(Graphics g) {
    double startAngle = getStartAngle();
    ColorUtils cu = new ColorUtils(dd.getXVals().length);
    double angleSize = ((CIRCLESIZE / (getSumX())));
    double items[] = dd.getXVals();
    for (int i = 0; i < items.length; i++) {

      //360.0 * items[i] / d.getSum();
      double centralAngle = (angleSize * items[i]);

      g.setColor(cu.getColor(i));
      g.fillArc(getCenterX(), getCenterY(),
                getRadius(), getRadius(),
                (int) (startAngle - 5), (int) (centralAngle + 5));
      startAngle = startAngle + centralAngle;
    }
  }

  /**
   *    Calculates the percentage of the pie occupied by each slice.
   *    Returns the value as a string so it can be written as a label on the
   *    pieGraph Panel.
   *
   *
   *    @return pctStrings      The percentage of the pie occupied by each slice
   *    @see                    #getSumX
   *    @see                    CreatePiePanel.#getLegendPanel
   */
  protected String[] calculatePercentage() {
    double sum = getSumX();
    double[] x = dd.getXVals();
    double[] percentages = new double[x.length];
    for (int i = 0; i < x.length; i++) {
      percentages[i] = (x[i] / sum) * 100;
    }

    String[] pctStrings = new String[percentages.length];
    for (int j = 0; j < pctStrings.length; j++) {
      pctStrings[j] = new String(Double.toString(percentages[j]) + "%");
      System.out.println("String=" + pctStrings[j]);
    }
    return pctStrings;
  }


  /**
   *    Computes the sum of all the data values. Used to calculate the percentage per slice
   *    of each data point in a pie graphics.graph.
   *
   *    @param _x       The array of data to add
   *    @return sum     Sum of data x
   *    @see            #getSumX
   */
  private double computeSum(double x[]) {
    double sum = 0;
    for (int i = 0; i < x.length; i++)
      sum = x[i] + sum;
    return sum;
  }

  /**
   *    Default no-argument method to calculate the sum of the array xVals, which is a global
   *    variable
   *
   *    @return sum     Sum of data xVals
   *    @see            #calculatePercentage
   */
  private double getSumX() {
    double sum = computeSum(dd.getXVals());
    return sum;
  }

  public static void main(String args[]) {
    ClosableJFrame cf = new ClosableJFrame();
    Container c = cf.getContentPane();
    DoubleData dd = new DoubleData(200, 200);
    double[] xes = new double[]{30, 30, 30, 60};


    for (int i = 0; i < dd.getXVals().length; i++) {
      double[] yes = dd.getXVals();
      System.out.println("value=" + yes[i]);
    }
    PieGraph pg = new PieGraph(200, 200);
    String[] labels = new String[]{"Tiger", "Lion", "Alligator", "Mongoose"};
    pg.setLabels(labels);
    pg.setValues(xes);
    c.add(pg);
    c.add(pg.getLegendPanel());
    c.setLayout(new FlowLayout());
    c.setBackground(Color.white);
    cf.setSize(300, 300);
    cf.setVisible(true);
  }

}