package net.sf.jasperreports.engine.base;

import java.awt.Color;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartPlot;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRVisitable;
import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
import net.sf.jasperreports.engine.util.JRStyleResolver;
import org.jfree.chart.plot.PlotOrientation;

public abstract class JRBaseChartPlot implements JRChartPlot, Serializable, JRChangeEventsSupport {
  private static final long serialVersionUID = 10200L;
  
  public static final String PROPERTY_BACKCOLOR = "backcolor";
  
  public static final String PROPERTY_BACKGROUND_ALPHA = "backgroundAlpha";
  
  public static final String PROPERTY_FOREGROUND_ALPHA = "foregroundAlpha";
  
  public static final String PROPERTY_LABEL_ROTATION = "labelRotation";
  
  public static final String PROPERTY_ORIENTATION = "orientation";
  
  public static final String PROPERTY_SERIES_COLORS = "seriesColors";
  
  protected JRChart chart = null;
  
  protected Color backcolor = null;
  
  protected PlotOrientation orientation = PlotOrientation.VERTICAL;
  
  protected float backgroundAlpha = 1.0F;
  
  protected float foregroundAlpha = 1.0F;
  
  protected double labelRotation = 0.0D;
  
  protected SortedSet seriesColors = null;
  
  private transient JRPropertyChangeSupport eventSupport;
  
  protected JRBaseChartPlot(JRChartPlot plot, JRChart chart) {
    this.chart = chart;
    if (plot != null) {
      this.backcolor = plot.getOwnBackcolor();
      this.orientation = plot.getOrientation();
      this.backgroundAlpha = plot.getBackgroundAlpha();
      this.foregroundAlpha = plot.getForegroundAlpha();
      this.labelRotation = plot.getLabelRotation();
      this.seriesColors = new TreeSet(plot.getSeriesColors());
    } else {
      this.seriesColors = new TreeSet();
    } 
  }
  
  protected JRBaseChartPlot(JRChartPlot plot, JRBaseObjectFactory factory) {
    factory.put(plot, this);
    this.chart = (JRChart)factory.getVisitResult((JRVisitable)plot.getChart());
    this.backcolor = plot.getOwnBackcolor();
    this.orientation = plot.getOrientation();
    this.backgroundAlpha = plot.getBackgroundAlpha();
    this.foregroundAlpha = plot.getForegroundAlpha();
    this.labelRotation = plot.getLabelRotation();
    this.seriesColors = new TreeSet(plot.getSeriesColors());
  }
  
  public JRChart getChart() {
    return this.chart;
  }
  
  public Color getBackcolor() {
    return JRStyleResolver.getBackcolor(this);
  }
  
  public Color getOwnBackcolor() {
    return this.backcolor;
  }
  
  public void setBackcolor(Color backcolor) {
    Object old = this.backcolor;
    this.backcolor = backcolor;
    getEventSupport().firePropertyChange("backcolor", old, this.backcolor);
  }
  
  public PlotOrientation getOrientation() {
    return this.orientation;
  }
  
  public void setOrientation(PlotOrientation orientation) {
    Object old = this.orientation;
    this.orientation = orientation;
    getEventSupport().firePropertyChange("orientation", old, this.orientation);
  }
  
  public float getBackgroundAlpha() {
    return this.backgroundAlpha;
  }
  
  public void setBackgroundAlpha(float backgroundAlpha) {
    float old = this.backgroundAlpha;
    this.backgroundAlpha = backgroundAlpha;
    getEventSupport().firePropertyChange("backgroundAlpha", old, this.backgroundAlpha);
  }
  
  public float getForegroundAlpha() {
    return this.foregroundAlpha;
  }
  
  public void setForegroundAlpha(float foregroundAlpha) {
    float old = this.foregroundAlpha;
    this.foregroundAlpha = foregroundAlpha;
    getEventSupport().firePropertyChange("foregroundAlpha", old, this.foregroundAlpha);
  }
  
  public double getLabelRotation() {
    return this.labelRotation;
  }
  
  public void setLabelRotation(double labelRotation) {
    double old = this.labelRotation;
    this.labelRotation = labelRotation;
    getEventSupport().firePropertyChange("labelRotation", old, this.labelRotation);
  }
  
  public SortedSet getSeriesColors() {
    return this.seriesColors;
  }
  
  public void clearSeriesColors() {
    setSeriesColors(null);
  }
  
  public void addSeriesColor(JRChartPlot.JRSeriesColor seriesColor) {
    this.seriesColors.add(seriesColor);
    getEventSupport().fireCollectionElementAddedEvent("seriesColors", seriesColor, this.seriesColors.size() - 1);
  }
  
  public void setSeriesColors(Collection colors) {
    Object old = new TreeSet(this.seriesColors);
    this.seriesColors.clear();
    if (colors != null)
      this.seriesColors.addAll(colors); 
    getEventSupport().firePropertyChange("seriesColors", old, this.seriesColors);
  }
  
  public static class JRBaseSeriesColor implements JRChartPlot.JRSeriesColor, Serializable, Comparable {
    private static final long serialVersionUID = 10200L;
    
    protected int seriesOrder = -1;
    
    protected Color color = null;
    
    public JRBaseSeriesColor(int seriesOrder, Color color) {
      this.seriesOrder = seriesOrder;
      this.color = color;
    }
    
    public int getSeriesOrder() {
      return this.seriesOrder;
    }
    
    public Color getColor() {
      return this.color;
    }
    
    public int compareTo(Object obj) {
      if (obj == null)
        throw new NullPointerException(); 
      return this.seriesOrder - ((JRBaseSeriesColor)obj).getSeriesOrder();
    }
    
    public Object clone() {
      try {
        return super.clone();
      } catch (CloneNotSupportedException e) {
        throw new JRRuntimeException(e);
      } 
    }
  }
  
  public Object clone(JRChart parentChart) {
    JRBaseChartPlot clone = null;
    try {
      clone = (JRBaseChartPlot)clone();
    } catch (CloneNotSupportedException e) {
      throw new JRRuntimeException(e);
    } 
    clone.chart = parentChart;
    if (this.seriesColors != null) {
      clone.seriesColors = new TreeSet();
      for (Iterator it = this.seriesColors.iterator(); it.hasNext();)
        clone.seriesColors.add(((JRChartPlot.JRSeriesColor)it.next()).clone()); 
    } 
    return clone;
  }
  
  public JRPropertyChangeSupport getEventSupport() {
    synchronized (this) {
      if (this.eventSupport == null)
        this.eventSupport = new JRPropertyChangeSupport(this); 
    } 
    return this.eventSupport;
  }
}
