/**
 * Copyright (C) 2012 Brookhaven National Laboratory
 * All rights reserved. Use is subject to license terms.
 */
package org.epics.graphene;

import java.awt.Color;
import java.awt.Graphics2D;
import java.util.Arrays;
import org.epics.util.array.ListNumber;
import org.epics.util.array.SortedListView;

/**
 * Renderer for a line graph.
 *
 * @author carcassi
 */
public class LineGraph2DRenderer extends Graph2DRenderer<LineGraph2DRendererUpdate> {

    public static java.util.List<InterpolationScheme> supportedInterpolationScheme = Arrays.asList(InterpolationScheme.NEAREST_NEIGHBOUR, InterpolationScheme.LINEAR, InterpolationScheme.CUBIC);
    public static java.util.List<ReductionScheme> supportedReductionScheme = Arrays.asList(ReductionScheme.FIRST_MAX_MIN_LAST, ReductionScheme.NONE);
    
    @Override
    public LineGraph2DRendererUpdate newUpdate() {
        return new LineGraph2DRendererUpdate();
    }

    private InterpolationScheme interpolation = InterpolationScheme.NEAREST_NEIGHBOUR;
    private ReductionScheme reduction = ReductionScheme.FIRST_MAX_MIN_LAST;

    /**
     * Creates a new line graph renderer.
     * 
     * @param imageWidth the graph width
     * @param imageHeight the graph height
     */
    public LineGraph2DRenderer(int imageWidth, int imageHeight) {
        super(imageWidth, imageHeight);
    }

    /**
     * The current interpolation used for the line.
     * 
     * @return the current interpolation
     */
    public InterpolationScheme getInterpolation() {
        return interpolation;
    }
    
    @Override
    public void update(LineGraph2DRendererUpdate update) {
        super.update(update);
        if (update.getInterpolation() != null) {
            interpolation = update.getInterpolation();
        }
        if (update.getDataReduction() != null) {
            reduction = update.getDataReduction();
        }
    }

    /**
     * Draws the graph on the given graphics context.
     * 
     * @param g the graphics on which to display the data
     * @param data the data to display
     */
    public void draw(Graphics2D g, Point2DDataset data) {
        this.g = g;
        
        calculateRanges(data.getXStatistics(), data.getYStatistics());
        calculateGraphArea();
        drawBackground();
        drawGraphArea();
        
        SortedListView xValues = org.epics.util.array.ListNumbers.sortedView(data.getXValues());
        ListNumber yValues = org.epics.util.array.ListNumbers.sortedView(data.getYValues(), xValues.getIndexes());

        setClip(g);
        g.setColor(Color.BLACK);
        drawValueExplicitLine(xValues, yValues, interpolation, reduction);
    }
}

@@ -1110,16 +1110,170 @@
 _LAST;%0D%0A
+    // Pixel focus%0D%0A    private Integer focusPixelX;%0D%0A    %0D%0A    private boolean highlightFocusValue = false;%0D%0A%0D%0A    private Integer focusValueIndex;%0D%0A    
 %0D%0A    /*
@@ -1750,32 +1750,294 @@
 ;%0D%0A    %7D%0D%0A    %0D%0A
+    public boolean isHighlightFocusValue() %7B%0D%0A        return highlightFocusValue;%0D%0A    %7D%0D%0A    %0D%0A    public int getFocusValueIndex() %7B%0D%0A        return focusValueIndex;%0D%0A    %7D%0D%0A    %0D%0A    public Integer getFocusPixelX() %7B%0D%0A        return focusPixelX;%0D%0A    %7D%0D%0A    %0D%0A
     @Override%0D%0A 
@@ -2352,24 +2352,134 @@
 %0A        %7D%0D%0A
+        if (update.getFocusPixelX()!= null) %7B%0D%0A            focusPixelX = update.getFocusPixelX();%0D%0A        %7D%0D%0A
     %7D%0D%0A%0D%0A   
@@ -3182,16 +3182,91 @@
 BLACK);%0D
+%0A%0D%0A        currentIndex = 0;%0D%0A        currentScaledDiff = getImageWidth();%0D
 %0A       
@@ -3338,14 +3338,628 @@
 );%0D%0A    
-%7D
+    if (focusPixelX != null) %7B%0D%0A            focusValueIndex = xValues.getIndexes().getInt(currentIndex);%0D%0A        %7D%0D%0A    %7D%0D%0A%0D%0A    @Override%0D%0A    protected void processScaledValue(int index, double valueX, double valueY, double scaledX, double scaledY) %7B%0D%0A        if (focusPixelX != null) %7B%0D%0A            double scaledDiff = Math.abs(scaledX - focusPixelX);%0D%0A            if (scaledDiff %3C currentScaledDiff) %7B%0D%0A                currentIndex = index;%0D%0A                currentScaledDiff = scaledDiff;%0D%0A            %7D%0D%0A        %7D%0D%0A    %7D%0D%0A    %0D%0A    private int currentIndex;%0D%0A    private double currentScaledDiff;%0D%0A    %0D%0A    
 %0D%0A%7D%0D%0A

line graph finds value closest to given value