/*
 * ChartBuilder.java
 *
 * Created on 2 de febrero de 2005, 06:22 PM
 */

package co.com.ddt.chart; 

import co.com.ddt.chart.bar.BarChartInfo;
import co.com.ddt.chart.line.LineChartInfo;
import co.com.ddt.chart.line.LineChartSerie;
import co.com.ddt.chart.pie.PieChartInfo;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.xy.XYSeriesCollection;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.plot.PlotOrientation;

import org.jfree.util.TableOrder;

import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

/**
 * Esta clase se encarga de construir instancias de los diferentes tipos
 * de chart (LINE, BAR, PIE) de acuerdo con la descripci&oacute;n proporcionada
 * por la informaci&oacute;n encapsulada en objetos derivados de <CODE>ChartInfo</CODE>
 * @author Mario Linares Vásquez
 */
public class ChartBuilder {
    
    /** Creates a new instance of ChartBuilder */
    private ChartBuilder() {
    
    
    }
    
    
    /**
     * Construye un objeto de tipo JFreeChart de acuerdo con el <CODE>ChartInfo</CODE>
     * pasado como parámetro. Por ejemplo para crear una g&aacute;fica de barras o lineal
     * los objetos par&aacute;metro deben ser instancias de de <CODE>BarChartInfo</CODE>
     * y <CODE>LineChartInfo</CODE> respectivamente
     * @param chartInfo Descripción del chart a crear
     * @return Chart generado
     */    
    public static JFreeChart buildChart(ChartInfo chartInfo){
    
        JFreeChart chart = null;
        int type = chartInfo.getType();
        
        if(type == ChartInfo.LINE){
          chart = ChartBuilder.buildLineChart((LineChartInfo)chartInfo);
        }
        else if(type == ChartInfo.BAR){
            chart = ChartBuilder.buildBarChart((BarChartInfo)chartInfo);
        }
        else if(type == ChartInfo.PIE){
         chart = ChartBuilder.buildPieChart((PieChartInfo)chartInfo);
        }
        
        return chart;
    }
    
    /**
     * Construye un objeto de tipo JFreeChart de acuerdo con el <CODE>ChartInfo</CODE>
     * pasado como parámetro y a continuaci&oacute;n genera una imagem en formato PNG
     * ,representativa del chart y para ser visualizado en un JSP.
     * @param chartInfo Descripci&oacute; del chart
     * @param request request Http
     * @return Path de la imagen
     */    
    public static String buildChartAndSavePNG(ChartInfo chartInfo,HttpServletRequest request){
        
        JFreeChart chart = ChartBuilder.buildChart(chartInfo);
        try{
            return ChartSaver.saveChartAsPNG(chart, request, chartInfo.getWidth(), chartInfo.getHeight());
        }
        catch(IOException ioe){
            System.out.println("Exception saving chart : ");
            ioe.printStackTrace();
            return null;
        }
    }
    
    /**
     * Construye un objeto de tipo JFreeChart de acuerdo con el <CODE>ChartInfo</CODE>
     * pasado como parámetro y a continuaci&oacute;n genera una imagem en formato JPEG
     * ,representativa del chart y para ser visualizado en un JSP.
     * @param chartInfo Descripci&oacute; del chart
     * @param request request Http
     * @return Path de la imagen
     */   
    public static String buildChartAndSaveJPEG(ChartInfo chartInfo,HttpServletRequest request){
        
        JFreeChart chart = ChartBuilder.buildChart(chartInfo);
        try{
            
            return System.getProperty("java.io.tmpdir")+"\\"+ChartSaver.saveChartAsJPEG(chart, request, chartInfo.getWidth(), chartInfo.getHeight());
        }
        catch(IOException ioe){
            System.out.println("Exception saving chart : ");
            ioe.printStackTrace();
            return null;
        }
    }    
    
    /**
     * Crea un JFreeChart de tipo l&iacute;nea
     * @param chartInfo Descripci&oacute;n del chart
     * @return Gr&aacute;fica generada
     */    
    private static JFreeChart buildLineChart(LineChartInfo chartInfo){
        
        String title = chartInfo.getTitle();
        title = (title == null?"":title);
        
        String xLabel = chartInfo.getXLabel();
        xLabel = (xLabel == null?"":xLabel);
        
        String yLabel = chartInfo.getYLabel();
        yLabel = (yLabel == null?"":yLabel);
        
        PlotOrientation orientation = chartInfo.getOrientation();
        orientation = (orientation == null ?PlotOrientation.VERTICAL:orientation);
        
        boolean legend = chartInfo.isLegend();
        
        boolean tooltips = chartInfo.isTooltips();
        
        Hashtable series = chartInfo.getSeries();
        Enumeration seriesEnum = series.keys();
        
        
        XYSeriesCollection xyDataset = new XYSeriesCollection();
       DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
         
        while(seriesEnum.hasMoreElements()){
        
          LineChartSerie chartSerie = (LineChartSerie)series.get(seriesEnum.nextElement());
          
          String serieName = chartSerie.getSerieName();
          serieName = (serieName == null?"":serieName);
          
          XYSeries serie = new XYSeries(serieName);
          
          Enumeration xEnum = chartSerie.getXValues().elements();
          Enumeration yEnum = chartSerie.getYValues().elements();
        
            while(xEnum.hasMoreElements()){
                Object x = xEnum.nextElement();
                Double y = (Double)yEnum.nextElement();
                //serie.add(x.doubleValue(),y.doubleValue());
                categoryDataset.addValue(y ,serieName ,x.toString());
                
            }
          
          //xyDataset.addSeries(serie);
        }
       JFreeChart chart = null;
         if(chartInfo.isChart3D()){
            chart = ChartFactory.createLineChart3D(title, xLabel, yLabel,categoryDataset, orientation,legend, tooltips,false);
         }
         else{
            chart = ChartFactory.createLineChart(title, xLabel, yLabel,categoryDataset, orientation,legend, tooltips,false);
         }
                

        //JFreeChart chart = ChartFactory.create XYLineChart(title, xLabel, yLabel, xyDataset, orientation,legend, tooltips,false);
        
        //XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)chart.getXYPlot().getRendererForDataset(xyDataset);
       //renderer.setDefaultShapesVisible(true);
        
        return chart;
    }
    
     /**
     * Crea un JFreeChart de barras
     * @param chartInfo Descripci&oacute;n del chart
     * @return Gr&aacute;fica generada
     */    
    private static JFreeChart buildBarChart(BarChartInfo chartInfo){
                
        String title = chartInfo.getTitle();
        title = (title == null?"":title);
        
        String xLabel = chartInfo.getXLabel();
        xLabel = (xLabel == null?"":xLabel);
        
        String yLabel = chartInfo.getYLabel();
        yLabel = (yLabel == null?"":yLabel);
        
        PlotOrientation orientation = chartInfo.getOrientation();
        orientation = (orientation == null ?PlotOrientation.VERTICAL:orientation);
        
        boolean legend = chartInfo.isLegend();
        
        boolean tooltips = chartInfo.isTooltips();
        
        
        String[] serieNames = new String[chartInfo.getSeriesSize()];
	String[] categoryNames = chartInfo.getCategoryNamesAsStringArray();
        
                
        Number[][] categoryData = new Number[categoryNames.length][serieNames.length];
	
        DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
        Enumeration seriesEnum = chartInfo.series.keys();
        
        int count = 0;
        
        while(seriesEnum.hasMoreElements()){
           
            String key = (String)seriesEnum.nextElement();
            
            serieNames[count] = key;
            
            Vector serie = ((ChartSerie)chartInfo.series.get(key)).getYValues();
            
            int count2 = 0;
            while(count2 < categoryNames.length){
                Double y = (Double)serie.elementAt(count2);
                y = (y==null?new Double(0.0):y);
                
                categoryDataset.addValue(y.doubleValue(),serieNames[count], categoryNames[count2]);
                
                count2++;
            }
            count++;
        }
        
        
        JFreeChart chart = null;
        if(chartInfo.isChart3D()){
            chart = ChartFactory.createBarChart3D( title, xLabel, yLabel, categoryDataset, orientation,legend, tooltips,false);
        }
        else{
            chart = ChartFactory.createBarChart( title, xLabel, yLabel, categoryDataset, orientation,legend, tooltips,false);
        }
            
        
        
        return chart;
    }
    
     /**
     * Crea un JFreeChart de tipo pie
     * @param chartInfo Descripci&oacute;n del chart
     * @return Gr&aacute;fica generada
     */    
     private static JFreeChart buildPieChart(PieChartInfo chartInfo){
                
        String title = chartInfo.getTitle();
        title = (title == null?"":title);
        
        
        boolean legend = chartInfo.isLegend();
        
        boolean tooltips = chartInfo.isTooltips();
        
        
        String[] serieNames = new String[chartInfo.getSeriesSize()];
	String[] categoryNames = chartInfo.getCategoryNamesAsStringArray();
        Number[][] categoryData = new Number[categoryNames.length][serieNames.length];
        
        
	
        DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
        Enumeration seriesEnum = chartInfo.series.keys();
        
        int count = 0;
        
        while(seriesEnum.hasMoreElements()){
        
            String key = (String)seriesEnum.nextElement();
            
            serieNames[count] = key;
            
            Vector serie = ((ChartSerie)chartInfo.series.get(key)).getYValues();
            
            int count2 = 0;
            while(count2 < categoryNames.length){
                Double y = (Double)serie.elementAt(count2);
                y = (y==null?new Double(0.0):y);
                
                categoryDataset.addValue(y.doubleValue(),serieNames[count], categoryNames[count2]);
                
                count2++;
            }
            count++;
        }
        
        
        JFreeChart chart = null;
        if(chartInfo.isChart3D()){
            chart = ChartFactory.createMultiplePieChart3D(title,categoryDataset,TableOrder.BY_COLUMN,false, tooltips,false);
            
        }
        else{
            chart = ChartFactory.createMultiplePieChart(title,categoryDataset,TableOrder.BY_COLUMN , false, tooltips,false);
            
        }
         
        
        
        return chart;
    }
}

// “Copyright (C) <2008> Multilateral Investment Fund of the Inter-American Development Bank.
// Este archivo es parte de <ICT4BUS-PVL>
// < ICT4BUS-PVL > es software libre: usted puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior.
// < ICT4BUS-PVL > se distribuye con la esperanza de que sea útil, pero SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO. 
// Consulte los detalles de la Licencia Pública General GNU para obtener una información más detallada. 
// Debería haber recibido una copia de la Licencia Pública General GNU junto a este programa. En caso contrario, consulte http://www.gnu.org/licenses/.”