/**
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * Copyright (C)
 * <a href="http://www.inab.org">Spanish National Institute of Bioinformatics (INB)</a>
 * <a href="http://www.bsc.es">Barcelona Supercomputing Center (BSC)</a>
 * <a href="http://inb.bsc.es">Computational Node 6</a>
 */

package org.inb.biomoby.client.gui.auxiliary;

import org.inb.biomoby.client.gui.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.util.List;
import org.inb.biomoby.client.gui.auxiliary.ArrayFloatChartPane.ArrayFloatListener;
import org.inb.biomoby.client.gui.IDynamicComponent.MobyComponentListener;
import org.inb.biomoby.shared.datatypes.MobyFloat;
import org.inb.biomoby.shared.datatypes.MobyInteger;
import org.inb.biomoby.shared.ontology.ArrayFloat;
import org.inb.biomoby.shared.ontology.ElementFloat;

/**
 * @author Dmitry Repchevsky
 */

public class ArrayFloatChartPane extends AbstractTransformableMobyPanel<ArrayFloatListener>
{
    private ArrayFloat arrayFloat;
    private Color color;
    
    public ArrayFloatChartPane() {}

    public ArrayFloatChartPane(ArrayFloat arrayFloat)
    {
        this.arrayFloat = arrayFloat;
    }

    public void setArrayFloat(ArrayFloat arrayFloat)
    {
        this.arrayFloat = arrayFloat;
        
        repaint();
    }

    public void setColor(Color color)
    {
        this.color = color;
    }
    
    @Override
    public Dimension getPreferredSize()
    {
        return new Dimension(120, 16);
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        if (arrayFloat != null)
        {
            Graphics2D g2d = (Graphics2D)g;

            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

            if (color != null)
            {
                g2d.setColor(color);
            }
            
            final int h = getHeight();
            
            List<? extends ElementFloat> elements = arrayFloat.getElement();
            
            if (elements != null)
            {
                boolean isBoolean = true;
                
                float min = Float.MAX_VALUE;
                float max = Float.MIN_VALUE;
                
                // looking for min/max values to calculate a scale...
                for (ElementFloat eFloat : elements)
                {
                    MobyFloat mobyFloat = eFloat.getValue();
                    
                    if (mobyFloat != null)
                    {
                        final float value = (float)mobyFloat.getFloat();
                        
                        min = Math.min(min, value);
                        max = Math.max(max, value);
                        
                        if (isBoolean && min != value && max != value)
                        {
                            isBoolean = false;
                        }
                    }
                }
                
                final float yScale = h/(max - min);

//                System.out.println("min = " + min + " max = " + max + " yScale = " + yScale);
                
                ISequenceCoordinateTransformer transformer = getTransformer();

                final int firstVisibleChar = transformer.getFirstVisibleChar();
                final int lastVisibleChar = transformer.getLastVisibleChar();

                Point2D.Float last = null;

                for (ElementFloat eFloat : elements)
                {
                    MobyInteger mobyInteger = eFloat.getKey();
                    MobyFloat mobyFloat = eFloat.getValue();
                    
                    Point2D.Float current = new Point2D.Float(0, mobyFloat != null ? ((float)mobyFloat.getFloat() - min) * yScale : 0);
                    
                    if (mobyInteger != null)
                    {
                        final int position = mobyInteger.getInteger();
                        
                        if (position >= firstVisibleChar)
                        {
                            current.x = (int)transformer.getXCharPosition(position);
                            
                            int x = last != null ? (int)last.x : 0;
                            int y = last != null ? (int)last.y : 0;
                            
                            if (isBoolean)
                            {
                                g2d.fillRect(x, y, (int)current.x - x, (int)current.y - y);
                            }
                            else
                            {
                                x = (x + ((int)current.x - x) / 2);
                                g2d.drawLine(x, y, (int)current.x, (int)current.y);
                                current.x = x;
                            }
                            
                            if (position > lastVisibleChar)
                            {
                                break;
                            }

                        }
                        last = current;
                    }                    
                }
            }
        }
    }
    
    public static interface ArrayFloatListener extends MobyComponentListener
    {
    }
}
