package bicat.gui;

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

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.urls.StandardXYURLGenerator;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.ui.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer3D;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;

import java.awt.Font;
import org.jfree.chart.axis.CategoryAnchor;
import org.jfree.chart.LegendItem;

import org.jfree.ui.TextAnchor;
import java.awt.Color;
import java.awt.Paint;
import org.jfree.chart.annotations.*;
import bicat.GO.FunctionalClass;
import java.text.DecimalFormat;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.title.Title;
/**
 * <p>
 * Title: BicAT Tool
 * </p>
 * <p>
 * Copyright: Copyright (c) 2004
 * </p>
 * 
 * @author D. Frick, A. Prelic
 * @version 1.0
 * 
 * 
 * Expression View tab
 */

public class FunctionPane extends JPanel // extends ChartPanel
		implements ActionListener {

    
    
     /**
     * A custom renderer that returns a different color for each item in a single series.
     */
    class CustomRenderer extends BarRenderer3D {

        /** The colors. */
        private Paint[] colors;

        /**
         * Creates a new renderer.
         *
         * @param colors  the colors.
         */
        public CustomRenderer(final Paint[] colors) {
            this.colors = colors;
        }

        /**
         * Returns the paint for an item.  Overrides the default behaviour inherited from
         * AbstractSeriesRenderer.
         *
         * @param row  the series.
         * @param column  the category.
         *
         * @return The item color.
         */
        public Paint getItemPaint(final int row, final int column) {
            return this.colors[column % this.colors.length];
        }
    }
    
    
    
    
    
    
	private static final int MAXIMUM_SIZE = 25;

	/** Hook to the governing <code>BicaGUI</code> object. */
	BicatGui owner;

	

	/** List of arrays containing expression values for graphs. */
	Vector graphDataList;

	/** Bounding rectangle of area that has been drawn to. */
	Rectangle filledRect;

	
	/** Array of preset colors to differentiate expression graphs. */
	Paint[] colorWheel;
        Color[] colorWheel_legend;
	// public ChartPanel() {}

	static int DEFAULT_X_TABLE = 3;

	// ===========================================================================
	/**
	 * Default constructor, initializes soem values.
	 * 
	 */
	public FunctionPane() {

		
		graphDataList = null;
		filledRect = new Rectangle(0, 0);
		// for the chart 
		colorWheel = new Paint[10]; // samo 8?
		colorWheel[0] = Color.CYAN;
		colorWheel[1] = Color.RED;
		colorWheel[2] = Color.GREEN;                    
		colorWheel[3] = Color.MAGENTA;
		colorWheel[4] = Color.PINK;
		colorWheel[5] = Color.ORANGE;
		colorWheel[6] = Color.BLUE;
		colorWheel[7] = Color.YELLOW;
                colorWheel[8]= Color.PINK.darker();
                colorWheel[9] = Color.magenta.darker();
      
                // for legend because it doesn't take paint 
                // if u change the chart colors,change the legend colors
                colorWheel_legend = new Color[10]; // samo 8?
		colorWheel_legend[0] = Color.CYAN;
		colorWheel_legend[1] = Color.RED;
		colorWheel_legend[2] = Color.GREEN;                    
		colorWheel_legend[3] = Color.MAGENTA;
		colorWheel_legend[4] = Color.PINK;
		colorWheel_legend[5] = Color.ORANGE;
		colorWheel_legend[6] = Color.BLUE;
		colorWheel_legend[7] = Color.YELLOW;
                colorWheel_legend[8]= Color.PINK.darker();
                colorWheel_legend[9] = Color.magenta.darker();
                
                
                
	}

	org.jfree.chart.JFreeChart chart;

	org.jfree.chart.ChartPanel chartPanel; // ChartPanel chartPanel;
	

	// ===========================================================================
	/**
	 * Hands the governing <code>BicaGUI</code> to this
	 * <code>GraphPane</code.>
	 */
	public void setOwner(BicatGui o) {
		owner = o;
	}

	// ===========================================================================
	/**
	 * For <code>ActionListener</code> interface, could be used to react to
	 * user input.
	 * 
	 */
	public void actionPerformed(ActionEvent e) {
		owner.functionScrollPane.repaint();
	}

	// ===========================================================================
	public void updateGraphic() {

		// this.remove(chartPanel);
                // get the column values   -log (pvalue)
            double [] _logPvalue=new double[graphDataList.size()];
            
            for(int i=0;i<graphDataList.size();i++)
            {
                //_logPvalue[i]=-1 * Math.log(((FunctionalClass)(graphDataList.get(i))).getRaw__Pvalue());
                _logPvalue[i]=-1 * Math.log10(((FunctionalClass)(graphDataList.get(i))).getRaw__Pvalue());
            }
            final double[][] data = new double[][]{_logPvalue};
             
            String [] category_labels=new String [graphDataList.size()];
            for(int i=0;i<graphDataList.size();i++)
            {
                category_labels[i]=((FunctionalClass)(graphDataList.get(i))).getName();
            }
            
            
            CategoryDataset dataset= DatasetUtilities.createCategoryDataset(new String []{"-log(Pvalue)"},category_labels, data);
        
            
            chart = createChart(dataset);
            chartPanel = new org.jfree.chart.ChartPanel(chart); // ChartPanel(chart);
            DrawLegendPanel legendpanel=new DrawLegendPanel();
            JPanel contentPane = new JPanel(new GridLayout(0, 1)); 
            
            contentPane.add(chartPanel);
            contentPane.add(legendpanel);
            
            
            
             this.removeAll();
             this.add(contentPane);
	     this.setVisible(true);
            chartPanel.revalidate();
	    owner.functionScrollPane.repaint();
	}

// ===========================================================================
	public void drawEnriched_Clusters(double [] percentage_Enriched_Clusters) {

		
            final double[][] data = new double[][]{percentage_Enriched_Clusters};
             
            String [] category_labels=new String [owner.PVALUE_ARRAY.length];
            for(int i=0;i<owner.PVALUE_ARRAY.length;i++)
            {
                category_labels[i]=""+owner.PVALUE_ARRAY[i];
            }
            
            
            CategoryDataset dataset= DatasetUtilities.createCategoryDataset(new String []{"percentage of functional enrichement"},category_labels, data);
        
            
            chart = create_Enriched_Clusters_Chart(dataset);
            chartPanel = new org.jfree.chart.ChartPanel(chart); // ChartPanel(chart);
            this.removeAll();
             this.add(chartPanel);
	     this.setVisible(true);
             chartPanel.revalidate();
	     owner.functionScrollPane.repaint();
	}
	
 private JFreeChart createChart(final CategoryDataset dataset) {
        
      
     //DecimalFormat df=new DecimalFormat("0.0000000");
     final JFreeChart chart = ChartFactory.createBarChart3D(
            "Bi/Cluster  Functional Analysis ",     // chart title
            "Enriched Functional Classes",       // domain axis label
            "-log(p-value)",                  // range axis label
            dataset,                  // data
            PlotOrientation.VERTICAL, // orientation
            false,                     // include legend
            true,                     // tooltips
            false                     // urls
        );
  
        //set the background
        Color c=new Color(228,228,228);
        chart.setBackgroundPaint(c);
        
        //set the pvalue tsubtitle 
        chart.addSubtitle(new TextTitle("p-value threshold  : "+ owner.P_VALUE_THRESHOLD));
        //chart.addSubtitle(new TextTitle("No of Enriched Functional Classes  : "+ graphDataList.size()));
         
       // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();
        plot.setNoDataMessage("NO DATA!");
        //plot.setBackgroundPaint();
        //plot.setForegroundAlpha(4);
      
        
         
        
        final CustomRenderer  renderer = new CustomRenderer(colorWheel);
        // renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
        renderer.setItemLabelsVisible(true);
       // renderer.setOutlinePaint(Color.BLACK);
        renderer.setDrawBarOutline(false);
       
        // for tool tip
        final BarRenderer3D renderer1 = (BarRenderer3D) plot.getRenderer();
        renderer.setToolTipGenerator(renderer1.getToolTipGenerator());
        //Annotation for displaying the percentage of enrichement
        CategoryTextAnnotation an=null;
        double gene_incluster=0;
        double gene_inpop=0;
        DecimalFormat df=new DecimalFormat("0.0");
        //adding the legend
        LegendItemCollection result = new LegendItemCollection();
        LegendItem item = null;
        
        for(int i=0;i<graphDataList.size();i++)
        {
                 
            gene_incluster=((FunctionalClass)graphDataList.get(i)).getContributed_Gene_No_In_Cluster();   
            gene_inpop=((FunctionalClass)graphDataList.get(i)).getContributed_Gene_No_In_Pop();  
           
              double percentage=gene_incluster *100/gene_inpop;
              double value=dataset.getValue(dataset.getRowKey(0),dataset.getColumnKey(i)).doubleValue();
              double position=value-(value*0.5); // put the percentage in the middle of column
          
                 
            an=new CategoryTextAnnotation(df.format(percentage)+"%",dataset.getColumnKey(i),position);
            an.setTextAnchor(TextAnchor.BOTTOM_CENTER);
            an.setFont(new Font("SansSerif", Font.BOLD, 12));
            an.setCategoryAnchor(CategoryAnchor.MIDDLE); 

            plot.addAnnotation(an);
            // the legend items
           item = new LegendItem( ((FunctionalClass)(graphDataList.get(i))).getName()+
                    "  "+((FunctionalClass)(graphDataList.get(i))).getDescription() +"\n"+"   "+
                    " percentage of Enrichement = "+df.format(percentage)+"%" +"   " ,
                     colorWheel[i % colorWheel.length]);
           // +"       " percentage of Enrichement = "+df.format(percentage)+"%" +"   " 
            result.add(item);
          
        }
        
        
         plot.setWeight(100);
         plot.setDomainGridlinesVisible(true);
         plot.setRangeGridlinesVisible(true);
         plot.setRenderer(renderer);
                
         final CategoryAxis axis = plot.getDomainAxis();
        axis.setCategoryLabelPositions(
            CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / dataset.getColumnCount())
        );
        
        System.out.println( dataset.getColumnCount());
        axis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
        axis.setCategoryMargin(0.4);
        axis.setUpperMargin(0.05);
        axis.setLowerMargin(0.05);
        // add the legend items
        //plot.setFixedLegendItems(result);
       
        
       
        return chart;

    }
private JFreeChart create_Enriched_Clusters_Chart(final CategoryDataset dataset) {
        
      
     //DecimalFormat df=new DecimalFormat("0.0000000");
     final JFreeChart chart = ChartFactory.createBarChart3D(
            "Bi/Cluster  Functional Analysis ",     // chart title
            "P-value threshold ",       // domain axis label
            "percentage of enriched Bi/Clusters (%)",                  // range axis label
            dataset,                  // data
            PlotOrientation.VERTICAL, // orientation
            true,                     // include legend
            true,                     // tooltips
            false                     // urls
        );
  
        //set the background
        Color c=new Color(228,228,228);
        chart.setBackgroundPaint(c);
        
        //set the pvalue tsubtitle 
        chart.addSubtitle(new TextTitle(" Percentage of Enriched Bi/clusters according to the standard p-values "));
        //chart.addSubtitle(new TextTitle("No of Enriched Functional Classes  : "+ graphDataList.size()));
         
        
        // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();
        plot.setNoDataMessage("NO DATA!");
        //plot.setBackgroundPaint();
        //plot.setForegroundAlpha(4);
      
        final CustomRenderer  renderer = new CustomRenderer(colorWheel);
        // renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
        renderer.setItemLabelsVisible(true);
        // renderer.setOutlinePaint(Color.BLACK);
        renderer.setDrawBarOutline(false);
        // for tool tip
        final BarRenderer3D renderer1 = (BarRenderer3D) plot.getRenderer();
        renderer.setToolTipGenerator(renderer1.getToolTipGenerator());
        
      
        LegendItemCollection result = new LegendItemCollection();
        LegendItem item = null;
        
        for(int i=0;i<owner.PVALUE_ARRAY.length;i++)
        {
                 
          
           item = new LegendItem("P-value threshold = " +owner.PVALUE_ARRAY[i] +"   " ,
                     colorWheel[i % colorWheel.length]);
                   result.add(item);
          
        }
        
        
         plot.setWeight(100);
         plot.setDomainGridlinesVisible(true);
         plot.setRangeGridlinesVisible(true);
         plot.setRenderer(renderer);
                
         final CategoryAxis axis = plot.getDomainAxis();
        axis.setCategoryLabelPositions(
            CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / dataset.getColumnCount())
        );
        
        System.out.println( dataset.getColumnCount());
        axis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
        axis.setCategoryMargin(0.4);
        axis.setUpperMargin(0.05);
        axis.setLowerMargin(0.05);
        // add the legend items
        plot.setFixedLegendItems(result);
       
        
       
        return chart;

    }         
    
        
	

	public Dimension getPictureSize() {
		if (0 != graphDataList.size())
			return new Dimension(0, 0);
		else
			return null;
	}

	// ===========================================================================
	/**
	 * Hands a list of selected genes and their respective expression value
	 * arrays to this <code>PicturePane</code>.
	 * 
	 */
	public void setGraphDataList(Vector graphs) {
		graphDataList = graphs;
		
	}
        
        public void clearPane()
        {
            
            this.removeAll();
	    this.setVisible(true);
            repaint();
        }

private JPanel createLegend() {
        
  return null;
    }
        




public class DrawLegendPanel extends JPanel {
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    
    
    //this.setBackground(new Color(228,228,228));
    this.setBackground(Color.white);
    this.setBorder( BorderFactory.createLineBorder(Color.BLACK,1));
    // set the size 20=color height+offset+margine
    this.setPreferredSize(new Dimension(this.getPreferredSize().width, 20*graphDataList.size()));
    
    String label_text="No of Enriched Functional Classes  : "+ graphDataList.size();
    g.setColor(Color.black);
    Font oldFont=g.getFont();
    // just to draw
    
    g.setFont(new Font("SansSerif", Font.BOLD, 13));
    int xlabel=((this.size().width)/2)-140;
    
    g.drawString(label_text,xlabel,17);
    
    
    int x=10;
    int y=27;
    int offsetx=5;
    int offsety=5;
    int width=12;
    int height=12;
    double percentage,gene_incluster,gene_inpop;
     DecimalFormat df=new DecimalFormat("0.0");
    // return the old font
     g.setFont(oldFont);
     
    for(int i =0;i<graphDataList.size();i++)
    {
      
        gene_incluster=((FunctionalClass)graphDataList.get(i)).getContributed_Gene_No_In_Cluster();   
        gene_inpop=((FunctionalClass)graphDataList.get(i)).getContributed_Gene_No_In_Pop();  
        percentage=gene_incluster *100/gene_inpop; 
       
        g.setColor(colorWheel_legend[i % colorWheel_legend.length]); 
        g.fillRect(x,y, width, height);
       
        g.setColor(Color.black);
        g.drawString(((FunctionalClass)(graphDataList.get(i))).getName()+
                    "  "+((FunctionalClass)(graphDataList.get(i))).getDescription() +"     percentage of Enrichement = "+df.format(percentage)+"%" +"   ",
                    x+width+offsetx, y+10);
       
       y=y+height+offsety;
     }
    
    
  }

}        
}
